Load essentiality data
Note I edited the headers of the tables before loading them. They now look like: “Orf t3_k t3_n t3_r t3_s t3_zbar”
t0 = read.table("data/essentiality/old/t0_essentiality.txt", skip=7)
colnames(t0) = c("Orf","t0_k","t0_n","t0_r","t0_s","t0_zbar")
t1 = read.table("data/essentiality/old/t1_essentiality.txt", skip=7)
colnames(t1) = c("Orf","t1_k","t1_n","t1_r","t1_s","t1_zbar")
t2 = read.table("data/essentiality/old/t2_essentiality.txt")
colnames(t2) = c("Orf","t2_k","t2_n","t2_r","t2_s","t2_zbar")
t3 = read.table("data/essentiality/old/t3_essentiality.txt")
colnames(t3) = c("Orf","t3_k","t3_n","t3_r","t3_s","t3_zbar")
essentiality_data = merge(t0, t1, by.x="Orf", by.y="Orf")
essentiality_data = merge(essentiality_data, t2, by.x="Orf", by.y="Orf")
essentiality_data = merge(essentiality_data, t3, by.x="Orf", by.y="Orf")
XLConnect::createSheet(workbook, name="essentiality_all")
XLConnect::writeWorksheet(workbook, essentiality_data, sheet="essentiality_all")
XLConnect::saveWorkbook(workbook)
Yoann asked about a venn diagram of this data. Here are 3 methods, one including a size-weighted which is completely silly because most of the hits are in the intersection of all 3.
t0_essential = t0
t1_essential = t1
t2_essential = t2
t0_essential$answer = ifelse(t0$t0_zbar > 0.99, 1, 0)
t1_essential$answer = ifelse(t1$t1_zbar > 0.99, 1, 0)
t2_essential$answer = ifelse(t2$t2_zbar > 0.99, 1, 0)
t0_essential = t0_essential[, c(1, 7)]
t1_essential = t1_essential[, c(1, 7)]
t2_essential = t2_essential[, c(1, 7)]
rownames(t0_essential) = t0_essential$Orf
##t0_essential = t0_essential[, -1]
rownames(t1_essential) = t1_essential$Orf
##t1_essential = t1_essential[, -1]
rownames(t2_essential) = t2_essential$Orf
##t2_essential = t2_essential[, -1]
essential_results = merge(t0_essential, t1_essential, by='row.names')
rownames(essential_results) = essential_results$Row.names
essential_results = essential_results[,-1]
essential_results = merge(essential_results, t2_essential, by='row.names')
rownames(essential_results) = essential_results$Row.names
essential_results = essential_results[, -1]
essential_results <- essential_results[, c("answer.x", "answer.y", "answer")]
## This is using limma's vennDiagram function
colnames(essential_results) = c("t0", "t1", "t2")
essential_counts = limma::vennCounts(essential_results)
limma::vennDiagram(essential_counts,
counts.col = c("blue", "red", "green"))

## I can use that to easily make the variables for the VennDiagram library...
i1 = 1
i2 = 8
i3 = 61
i12 = 1
i13 = 4
i23 = 85
i123 = 230
area1 = i1 + i12 + i13 + i123
area2 = i2 + i12 + i23 + i123
area3 = i3 + i13 + i23 + i123
n123 = i123
n12 = i12 + i123
n13 = i13 + i123
n23 = i23 + i123
test = Vennerable::Venn(SetNames = c("t0","t1","t2"), Weight =
c('100' = i1, '010' = i2, '001' = i3, ## The loners
'110' = i12, '011' = i23, '101' = i13, ## The doubles
'111' = i123))
Vennerable::plot(test, doWeights = TRUE, type = "circles")

Vennerable::plot(test, doWeights = FALSE, type = "circles")
draw.triple.venn(area1, area2, area3, n12, n23, n13, n123,
category = rep("", 3), rotation = 1, reverse = FALSE, euler.d = TRUE,
scaled = TRUE, lwd = rep(2, 3), lty = rep("solid", 3),
col = rep("black", 3), fill = NULL, alpha = rep(0.5, 3),
label.col = rep("black", 7), cex = rep(1, 7), fontface = rep("plain", 7),
fontfamily = rep("serif", 7), cat.pos = c(-40, 40, 180),
cat.dist = c(0.05, 0.05, 0.025), cat.col = rep("black", 3),
cat.cex = rep(1, 3), cat.fontface = rep("plain", 3),
cat.fontfamily = rep("serif", 3),
cat.just = list(c(0.5, 1), c(0.5, 1), c(0.5, 0)), cat.default.pos = "outer",
cat.prompts = FALSE, rotation.degree = 0, rotation.centre = c(0.5, 0.5),
ind = TRUE, sep.dist = 0.05, offset = 0)

## (polygon[GRID.polygon.702], polygon[GRID.polygon.703], polygon[GRID.polygon.704], polygon[GRID.polygon.705], polygon[GRID.polygon.706], polygon[GRID.polygon.707], text[GRID.text.708], text[GRID.text.709], text[GRID.text.710], text[GRID.text.711], text[GRID.text.712], text[GRID.text.713], text[GRID.text.714], text[GRID.text.715], text[GRID.text.716], text[GRID.text.717])
Repeat for the Alabama and NZ131 strains.
Add annotation information for Alabama and NZ131 into the excel workbook
Run essentiality and add the essentiality output to the excel workbook…
I created an alabama directory inside the essentiality directory. It took me a few tries to get it correct, and I had to make some small edits to the perl script tnseq_TAs to accomodate the new strains, but I ran the perlscript in the same fashion. (Caveat: The perl script needs to be able to cross reference the name of the fasta sequence against the bam sequence name. This tripped me up terribly.
Upon completion, I wrote a tiny shell script to run the python essentiality package for each output file.
cd essentiality/alabama/
./README.sh
## This prints out the appropriate command lines for the TNseq_TAs.pl and gumbelMH.py commands.
That completed in some hours, providing the raw outputs from essentiality, which I again edited slightly to include the timepoint values. Let us load them into the excel spreadsheet.
alabama_t0 = read.table("data/essentiality/old/Alab49_t0_essentiality.out", skip=7, header=TRUE)
alabama_t1 = read.table("data/essentiality/old/Alab49_t1_essentiality.out", skip=7, header=TRUE)
alabama_t2 = read.table("data/essentiality/old/Alab49_t2_essentiality.out", skip=7, header=TRUE)
alabama_t3 = read.table("data/essentiality/old/Alab49_t3_essentiality.out", skip=7, header=TRUE)
nz_t0 = read.table("data/essentiality/old/NZ131_t0_essentiality.out", skip=7, header=TRUE)
nz_t1 = read.table("data/essentiality/old/NZ131_t1_essentiality.out", skip=7, header=TRUE)
nz_t2 = read.table("data/essentiality/old/NZ131_t2_essentiality.out", skip=7, header=TRUE)
nz_t3 = read.table("data/essentiality/old/NZ131_t3_essentiality.out", skip=7, header=TRUE)
alabama_essentials = merge(alabama_t0, alabama_t1, by.x="Orf", by.y="Orf")
alabama_essentials = merge(alabama_essentials, alabama_t2, by.x="Orf", by.y="Orf")
alabama_essentials = merge(alabama_essentials, alabama_t3, by.x="Orf", by.y="Orf")
nz_essentials = merge(nz_t0, nz_t1, by.x="Orf", by.y="Orf")
nz_essentials = merge(nz_essentials, nz_t2, by.x="Orf", by.y="Orf")
nz_essentials = merge(nz_essentials, nz_t3, by.x="Orf", by.y="Orf")
head(nz_essentials)
## Orf t0_k t0_n t0_r t0_s t0_zbar t1_k t1_n t1_r t1_s t1_zbar t2_k
## 1 Spy49_0001 1 105 56 657 1.000 14 105 13 150 0.001 3
## 2 Spy49_0002 2 99 97 1100 1.000 9 99 28 311 1.000 1
## 3 Spy49_0003 3 15 5 73 0.000 12 15 1 2 0.000 12
## 4 Spy49_0004 21 80 11 97 0.001 65 80 2 9 0.000 54
## 5 Spy49_0005 1 56 43 414 0.999 12 56 14 161 0.034 2
## 6 Spy49_0006 74 256 14 179 0.001 191 256 4 42 0.000 111
## t2_n t2_r t2_s t2_zbar t3_k t3_n t3_r t3_s t3_zbar
## 1 105 39 537 0.998 4 105 39 537 0.102
## 2 99 78 910 1.000 6 99 24 255 0.002
## 3 15 1 2 0.000 4 15 6 51 0.001
## 4 80 2 9 0.000 28 80 11 97 0.001
## 5 56 28 240 0.189 5 56 22 252 0.003
## 6 256 10 141 0.000 61 256 21 311 0.024
XLConnect::createSheet(workbook, name="alabama_essentiality")
XLConnect::writeWorksheet(workbook, alabama_essentials, sheet="alabama_essentiality")
XLConnect::saveWorkbook(workbook)
XLConnect::createSheet(workbook, name="nz131_essentiality")
XLConnect::writeWorksheet(workbook, nz_essentials, sheet="nz131_essentiality")
XLConnect::saveWorkbook(workbook)
LS0tCnRpdGxlOiAiMjAxNTogVGhlIGZpcnN0IFROU2VxIG9mIFMucHlvZ2VuZXMiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeShocGdsdG9vbHMpCiAgdHQgPC0gZGV2dG9vbHM6OmxvYWRfYWxsKCJ+L2hwZ2x0b29scyIpCiAga25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgd2lkdGg9OTAsCiAgICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQogIGtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICBmaWcud2lkdGg9OCwKICAgICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCiAgb2xkX29wdGlvbnMgPC0gb3B0aW9ucyhkaWdpdHM9NCwKICAgICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKICBnZ3Bsb3QyOjp0aGVtZV9zZXQoZ2dwbG90Mjo6dGhlbWVfYncoYmFzZV9zaXplPTEwKSkKICB2ZXIgPC0gIjIwMTcxMTAyIgogIHByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCiAgdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkpCiAgcm1kX2ZpbGUgPC0gImVzc2VudGlhbGl0eS5SbWQiCn0KYGBgCgojIFF1aWNrIGNhdmVhdDogIFRoaXMgd2FzIG9uZSBvZiBteSBlYXJsaWVzdCBhbmFseXNlcyBhbmQgaXQgdGhlcmVmb3JlIGlzLi4uIGJhZC4KCkkgYW0gdGhlcmVmb3JlIGRvaW5nIHRvIGJhcmUgbWluaW11bSByZXF1aXJlZCB0byBiZSBhYmxlIHRvIG9uY2UgYWdhaW4gZ2xlYW4KdXNlZnVsIGluZm9ybWF0aW9uIGZyb20gaXQuCgpgYGB7ciBsb2FkLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KGhwZ2x0b29scykKcGxlYXNlX2luc3RhbGwoIlZlbm5EaWFncmFtIikKbG9hZCgiUkRhdGEiKQp3b3JrYm9vayA9IFhMQ29ubmVjdDo6bG9hZFdvcmtib29rKCJleGNlbC90bnNlcV93b3JrYm9vay54bHMiLCBjcmVhdGU9VFJVRSkKYGBgCgpbbGFzdF0oY2JjYlNFUS5odG1sKSwKPGEgaHJlZj0iIyIgb25jbGljaz0iaGlzdG9yeS5nbygtMSkiPmdvIGJhY2s8L2E+CltpbmRleF0oaW5kZXguaHRtbCksIFtuZXh0XShlc3NlbnRpYWxpdHkuaHRtbCkKCgojIEVzc2VudGlhbGl0eQoKVGhpcyBpcyBydW4gd2l0aCB0aGUgZm9sbG93aW5nIGNvbW1hbmQgbGluZSBhbmQgcHJpbnRzIG91dCBhIHRhYmxlIG9mIHogc2NvcmVzLgpUaGlzIHJlcXVpcmVzIGEgZmlsZSBUQV9kYXRhLnR4dCB3aGljaCBpbiB0dXJuIGNvbWVzIGZyb20gYSBzbWFsbCBwZXJsIHNjcmlwdAp3aGljaCByZWFkcyBvdmVyIHRoZSBiYW0gZmlsZXMgYW5kIHByaW50cyB0aGUgIyBvZiBpbnNlcnRpb25zIHdoaWNoIGZhbGwgZXhhY3RseQppbiB0aGUgY29ycmVjdCBvcmllbnRhdGlvbiBhdCBlYWNoIFRBIHBvc2l0aW9uIGluIHRoZSBnZW5vbWUuCgpgYGB7ciBlc3NlbnRpYWxpdHlfcnVubmluZywgZW5naW5lPSdiYXNoJywgZXZhbD1GQUxTRX0KZm9yIGRpciBpbiB0MCB0MSB0MiB0MzsgZG8KICBwZXJsIHRuc2VxX1RBcy5wbCAtaSAuLi9ydW4zL2xpYnMvcmFuZG9tXzFtaXNtYXRjaC9saWIxXyR7ZGlyfV9zb3J0ZWQuYmFtIDI+JHtkaXJ9L3Ruc2VxX1RBcy5lcnIgMT4ke2Rpcn0vdG5zZXFfVEFzLm91dAogIHB5dGhvbiBndW1iZWxNSC5weSAtZiAke2Rpcn0vdG5zZXFfVEFzLm91dCAtbSAxIC1zIDEwMDAgMj4ke2Rpcn0vZXNzZW50aWFsaXR5LmVyciAxPiR7ZGlyfS9lc3NlbnRpYWxpdHkub3V0CmRvbmUKYGBgCgpVcG9uIGNvbXBsZXRpb24sIEkgaGF2ZSA0IGRpcmVjdG9yaWVzIGNvbnRhaW5pbmcgdGhlIGVzc2VudGlhbGl0eS5vdXQgZmlsZXMuClRoZXNlIGFyZSBjb3BpZWQgaW50byBbZGF0YS9lc3NlbnRpYWxpdHkvXShkYXRhL2Vzc2VudGlhbGl0eS8pLgoKIyBMb2FkIGVzc2VudGlhbGl0eSBkYXRhCgpOb3RlIEkgZWRpdGVkIHRoZSBoZWFkZXJzIG9mIHRoZSB0YWJsZXMgYmVmb3JlIGxvYWRpbmcgdGhlbS4gIFRoZXkgbm93IGxvb2sgbGlrZToKIk9yZgl0M19rCXQzX24JdDNfcgl0M19zCXQzX3piYXIiCgpgYGB7ciBsb2FkX2Vzc2VudGlhbGl0eX0KdDAgPSByZWFkLnRhYmxlKCJkYXRhL2Vzc2VudGlhbGl0eS9vbGQvdDBfZXNzZW50aWFsaXR5LnR4dCIsIHNraXA9NykKY29sbmFtZXModDApID0gYygiT3JmIiwidDBfayIsInQwX24iLCJ0MF9yIiwidDBfcyIsInQwX3piYXIiKQp0MSA9IHJlYWQudGFibGUoImRhdGEvZXNzZW50aWFsaXR5L29sZC90MV9lc3NlbnRpYWxpdHkudHh0Iiwgc2tpcD03KQpjb2xuYW1lcyh0MSkgPSBjKCJPcmYiLCJ0MV9rIiwidDFfbiIsInQxX3IiLCJ0MV9zIiwidDFfemJhciIpCnQyID0gcmVhZC50YWJsZSgiZGF0YS9lc3NlbnRpYWxpdHkvb2xkL3QyX2Vzc2VudGlhbGl0eS50eHQiKQpjb2xuYW1lcyh0MikgPSBjKCJPcmYiLCJ0Ml9rIiwidDJfbiIsInQyX3IiLCJ0Ml9zIiwidDJfemJhciIpCnQzID0gcmVhZC50YWJsZSgiZGF0YS9lc3NlbnRpYWxpdHkvb2xkL3QzX2Vzc2VudGlhbGl0eS50eHQiKQpjb2xuYW1lcyh0MykgPSBjKCJPcmYiLCJ0M19rIiwidDNfbiIsInQzX3IiLCJ0M19zIiwidDNfemJhciIpCmVzc2VudGlhbGl0eV9kYXRhID0gbWVyZ2UodDAsIHQxLCBieS54PSJPcmYiLCBieS55PSJPcmYiKQplc3NlbnRpYWxpdHlfZGF0YSA9IG1lcmdlKGVzc2VudGlhbGl0eV9kYXRhLCB0MiwgYnkueD0iT3JmIiwgYnkueT0iT3JmIikKZXNzZW50aWFsaXR5X2RhdGEgPSBtZXJnZShlc3NlbnRpYWxpdHlfZGF0YSwgdDMsIGJ5Lng9Ik9yZiIsIGJ5Lnk9Ik9yZiIpCgpYTENvbm5lY3Q6OmNyZWF0ZVNoZWV0KHdvcmtib29rLCBuYW1lPSJlc3NlbnRpYWxpdHlfYWxsIikKWExDb25uZWN0Ojp3cml0ZVdvcmtzaGVldCh3b3JrYm9vaywgZXNzZW50aWFsaXR5X2RhdGEsIHNoZWV0PSJlc3NlbnRpYWxpdHlfYWxsIikKWExDb25uZWN0OjpzYXZlV29ya2Jvb2sod29ya2Jvb2spCmBgYAoKWW9hbm4gYXNrZWQgYWJvdXQgYSB2ZW5uIGRpYWdyYW0gb2YgdGhpcyBkYXRhLiAgSGVyZSBhcmUgMyBtZXRob2RzLCBvbmUKaW5jbHVkaW5nIGEgc2l6ZS13ZWlnaHRlZCB3aGljaCBpcyBjb21wbGV0ZWx5IHNpbGx5IGJlY2F1c2UgbW9zdCBvZiB0aGUgaGl0cyBhcmUKaW4gdGhlIGludGVyc2VjdGlvbiBvZiBhbGwgMy4KCmBgYHtyIGVzc2VudGlhbGl0eV92ZW5ufQp0MF9lc3NlbnRpYWwgPSB0MAp0MV9lc3NlbnRpYWwgPSB0MQp0Ml9lc3NlbnRpYWwgPSB0Mgp0MF9lc3NlbnRpYWwkYW5zd2VyID0gaWZlbHNlKHQwJHQwX3piYXIgPiAwLjk5LCAxLCAwKQp0MV9lc3NlbnRpYWwkYW5zd2VyID0gaWZlbHNlKHQxJHQxX3piYXIgPiAwLjk5LCAxLCAwKQp0Ml9lc3NlbnRpYWwkYW5zd2VyID0gaWZlbHNlKHQyJHQyX3piYXIgPiAwLjk5LCAxLCAwKQp0MF9lc3NlbnRpYWwgPSB0MF9lc3NlbnRpYWxbLCBjKDEsIDcpXQp0MV9lc3NlbnRpYWwgPSB0MV9lc3NlbnRpYWxbLCBjKDEsIDcpXQp0Ml9lc3NlbnRpYWwgPSB0Ml9lc3NlbnRpYWxbLCBjKDEsIDcpXQpyb3duYW1lcyh0MF9lc3NlbnRpYWwpID0gdDBfZXNzZW50aWFsJE9yZgojI3QwX2Vzc2VudGlhbCA9IHQwX2Vzc2VudGlhbFssIC0xXQpyb3duYW1lcyh0MV9lc3NlbnRpYWwpID0gdDFfZXNzZW50aWFsJE9yZgojI3QxX2Vzc2VudGlhbCA9IHQxX2Vzc2VudGlhbFssIC0xXQpyb3duYW1lcyh0Ml9lc3NlbnRpYWwpID0gdDJfZXNzZW50aWFsJE9yZgojI3QyX2Vzc2VudGlhbCA9IHQyX2Vzc2VudGlhbFssIC0xXQplc3NlbnRpYWxfcmVzdWx0cyA9IG1lcmdlKHQwX2Vzc2VudGlhbCwgdDFfZXNzZW50aWFsLCBieT0ncm93Lm5hbWVzJykKcm93bmFtZXMoZXNzZW50aWFsX3Jlc3VsdHMpID0gZXNzZW50aWFsX3Jlc3VsdHMkUm93Lm5hbWVzCmVzc2VudGlhbF9yZXN1bHRzID0gZXNzZW50aWFsX3Jlc3VsdHNbLC0xXQplc3NlbnRpYWxfcmVzdWx0cyA9IG1lcmdlKGVzc2VudGlhbF9yZXN1bHRzLCB0Ml9lc3NlbnRpYWwsIGJ5PSdyb3cubmFtZXMnKQpyb3duYW1lcyhlc3NlbnRpYWxfcmVzdWx0cykgPSBlc3NlbnRpYWxfcmVzdWx0cyRSb3cubmFtZXMKZXNzZW50aWFsX3Jlc3VsdHMgPSBlc3NlbnRpYWxfcmVzdWx0c1ssIC0xXQplc3NlbnRpYWxfcmVzdWx0cyA8LSBlc3NlbnRpYWxfcmVzdWx0c1ssIGMoImFuc3dlci54IiwgImFuc3dlci55IiwgImFuc3dlciIpXQojIyBUaGlzIGlzIHVzaW5nIGxpbW1hJ3MgdmVubkRpYWdyYW0gZnVuY3Rpb24KY29sbmFtZXMoZXNzZW50aWFsX3Jlc3VsdHMpID0gYygidDAiLCAidDEiLCAidDIiKQplc3NlbnRpYWxfY291bnRzID0gbGltbWE6OnZlbm5Db3VudHMoZXNzZW50aWFsX3Jlc3VsdHMpCmxpbW1hOjp2ZW5uRGlhZ3JhbShlc3NlbnRpYWxfY291bnRzLAogICAgICAgICAgICAgICAgICAgY291bnRzLmNvbCA9IGMoImJsdWUiLCAicmVkIiwgImdyZWVuIikpCiMjIEkgY2FuIHVzZSB0aGF0IHRvIGVhc2lseSBtYWtlIHRoZSB2YXJpYWJsZXMgZm9yIHRoZSBWZW5uRGlhZ3JhbSBsaWJyYXJ5Li4uCgppMSA9IDEKaTIgPSA4CmkzID0gNjEKaTEyID0gMQppMTMgPSA0CmkyMyA9IDg1CmkxMjMgPSAyMzAKCmFyZWExID0gaTEgKyBpMTIgKyBpMTMgKyBpMTIzCmFyZWEyID0gaTIgKyBpMTIgKyBpMjMgKyBpMTIzCmFyZWEzID0gaTMgKyBpMTMgKyBpMjMgKyBpMTIzCgpuMTIzID0gaTEyMwpuMTIgPSBpMTIgKyBpMTIzCm4xMyA9IGkxMyArIGkxMjMKbjIzID0gaTIzICsgaTEyMwoKdGVzdCA9IFZlbm5lcmFibGU6OlZlbm4oU2V0TmFtZXMgPSBjKCJ0MCIsInQxIiwidDIiKSwgV2VpZ2h0ID0KICAgIGMoJzEwMCcgPSBpMSwgJzAxMCcgPSBpMiwgJzAwMScgPSBpMywgIyMgVGhlIGxvbmVycwogICAgICAnMTEwJyA9IGkxMiwgJzAxMScgPSBpMjMsICcxMDEnID0gaTEzLCAgIyMgVGhlIGRvdWJsZXMKICAgICAgJzExMScgPSBpMTIzKSkKVmVubmVyYWJsZTo6cGxvdCh0ZXN0LCBkb1dlaWdodHMgPSBUUlVFLCB0eXBlID0gImNpcmNsZXMiKQpWZW5uZXJhYmxlOjpwbG90KHRlc3QsIGRvV2VpZ2h0cyA9IEZBTFNFLCB0eXBlID0gImNpcmNsZXMiKQoKZHJhdy50cmlwbGUudmVubihhcmVhMSwgYXJlYTIsIGFyZWEzLCBuMTIsIG4yMywgbjEzLCBuMTIzLAogICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gcmVwKCIiLCAzKSwgcm90YXRpb24gPSAxLCByZXZlcnNlID0gRkFMU0UsIGV1bGVyLmQgPSBUUlVFLAogICAgICAgICAgICAgICAgIHNjYWxlZCA9IFRSVUUsIGx3ZCA9IHJlcCgyLCAzKSwgbHR5ID0gcmVwKCJzb2xpZCIsIDMpLAogICAgICAgICAgICAgICAgIGNvbCA9IHJlcCgiYmxhY2siLCAzKSwgZmlsbCA9IE5VTEwsIGFscGhhID0gcmVwKDAuNSwgMyksCiAgICAgICAgICAgICAgICAgbGFiZWwuY29sID0gcmVwKCJibGFjayIsIDcpLCBjZXggPSByZXAoMSwgNyksIGZvbnRmYWNlID0gcmVwKCJwbGFpbiIsIDcpLAogICAgICAgICAgICAgICAgIGZvbnRmYW1pbHkgPSByZXAoInNlcmlmIiwgNyksIGNhdC5wb3MgPSBjKC00MCwgNDAsIDE4MCksCiAgICAgICAgICAgICAgICAgY2F0LmRpc3QgPSBjKDAuMDUsIDAuMDUsIDAuMDI1KSwgY2F0LmNvbCA9IHJlcCgiYmxhY2siLCAzKSwKICAgICAgICAgICAgICAgICBjYXQuY2V4ID0gcmVwKDEsIDMpLCBjYXQuZm9udGZhY2UgPSByZXAoInBsYWluIiwgMyksCiAgICAgICAgICAgICAgICAgY2F0LmZvbnRmYW1pbHkgPSByZXAoInNlcmlmIiwgMyksCiAgICAgICAgICAgICAgICAgY2F0Lmp1c3QgPSBsaXN0KGMoMC41LCAxKSwgYygwLjUsIDEpLCBjKDAuNSwgMCkpLCBjYXQuZGVmYXVsdC5wb3MgPSAib3V0ZXIiLAogICAgICAgICAgICAgICAgIGNhdC5wcm9tcHRzID0gRkFMU0UsIHJvdGF0aW9uLmRlZ3JlZSA9IDAsIHJvdGF0aW9uLmNlbnRyZSA9IGMoMC41LCAwLjUpLAogICAgICAgICAgICAgICAgIGluZCA9IFRSVUUsIHNlcC5kaXN0ID0gMC4wNSwgb2Zmc2V0ID0gMCkKYGBgCgojIFJlcGVhdCBmb3IgdGhlIEFsYWJhbWEgYW5kIE5aMTMxIHN0cmFpbnMuCgojIyBBZGQgYW5ub3RhdGlvbiBpbmZvcm1hdGlvbiBmb3IgQWxhYmFtYSBhbmQgTloxMzEgaW50byB0aGUgZXhjZWwgd29ya2Jvb2sKCiMjIFJ1biBlc3NlbnRpYWxpdHkgYW5kIGFkZCB0aGUgZXNzZW50aWFsaXR5IG91dHB1dCB0byB0aGUgZXhjZWwgd29ya2Jvb2suLi4KCkkgY3JlYXRlZCBhbiBhbGFiYW1hIGRpcmVjdG9yeSBpbnNpZGUgdGhlIGVzc2VudGlhbGl0eSBkaXJlY3RvcnkuICBJdCB0b29rIG1lIGEgZmV3IHRyaWVzIHRvIGdldCBpdCBjb3JyZWN0LCBhbmQgSSBoYWQgdG8gbWFrZSBzb21lIHNtYWxsIGVkaXRzIHRvIHRoZSBwZXJsIHNjcmlwdCB0bnNlcV9UQXMgdG8gYWNjb21vZGF0ZSB0aGUgbmV3IHN0cmFpbnMsIGJ1dCBJIHJhbiB0aGUgcGVybHNjcmlwdCBpbiB0aGUgc2FtZSBmYXNoaW9uLiAgKENhdmVhdDogIFRoZSBwZXJsIHNjcmlwdCBuZWVkcyB0byBiZSBhYmxlIHRvIGNyb3NzIHJlZmVyZW5jZSB0aGUgbmFtZSBvZiB0aGUgX2Zhc3RhXyBzZXF1ZW5jZSBhZ2FpbnN0IHRoZSBiYW0gc2VxdWVuY2UgbmFtZS4gIFRoaXMgdHJpcHBlZCBtZSB1cCB0ZXJyaWJseS4KClVwb24gY29tcGxldGlvbiwgSSB3cm90ZSBhIHRpbnkgc2hlbGwgc2NyaXB0IHRvIHJ1biB0aGUgcHl0aG9uIGVzc2VudGlhbGl0eSBwYWNrYWdlIGZvciBlYWNoIG91dHB1dCBmaWxlLgoKYGBge3IgYWxhYmFtYV9lc3NlbnRpYWxpdHksIGVuZ2luZz0nYmFzaCcsIGV2YWw9RkFMU0V9CmNkIGVzc2VudGlhbGl0eS9hbGFiYW1hLwouL1JFQURNRS5zaAojIyBUaGlzIHByaW50cyBvdXQgdGhlIGFwcHJvcHJpYXRlIGNvbW1hbmQgbGluZXMgZm9yIHRoZSBUTnNlcV9UQXMucGwgYW5kIGd1bWJlbE1ILnB5IGNvbW1hbmRzLgpgYGAKClRoYXQgY29tcGxldGVkIGluIHNvbWUgaG91cnMsIHByb3ZpZGluZyB0aGUgcmF3IG91dHB1dHMgZnJvbSBlc3NlbnRpYWxpdHksIHdoaWNoIEkgYWdhaW4gZWRpdGVkIHNsaWdodGx5IHRvIGluY2x1ZGUgdGhlIHRpbWVwb2ludCB2YWx1ZXMuICBMZXQgdXMgbG9hZCB0aGVtIGludG8gdGhlIGV4Y2VsIHNwcmVhZHNoZWV0LgoKYGBge3IgbG9hZF9hbGFiYW1hX2Vzc2VudGlhbGl0eX0KYWxhYmFtYV90MCA9IHJlYWQudGFibGUoImRhdGEvZXNzZW50aWFsaXR5L29sZC9BbGFiNDlfdDBfZXNzZW50aWFsaXR5Lm91dCIsIHNraXA9NywgaGVhZGVyPVRSVUUpCmFsYWJhbWFfdDEgPSByZWFkLnRhYmxlKCJkYXRhL2Vzc2VudGlhbGl0eS9vbGQvQWxhYjQ5X3QxX2Vzc2VudGlhbGl0eS5vdXQiLCBza2lwPTcsIGhlYWRlcj1UUlVFKQphbGFiYW1hX3QyID0gcmVhZC50YWJsZSgiZGF0YS9lc3NlbnRpYWxpdHkvb2xkL0FsYWI0OV90Ml9lc3NlbnRpYWxpdHkub3V0Iiwgc2tpcD03LCBoZWFkZXI9VFJVRSkKYWxhYmFtYV90MyA9IHJlYWQudGFibGUoImRhdGEvZXNzZW50aWFsaXR5L29sZC9BbGFiNDlfdDNfZXNzZW50aWFsaXR5Lm91dCIsIHNraXA9NywgaGVhZGVyPVRSVUUpCm56X3QwID0gcmVhZC50YWJsZSgiZGF0YS9lc3NlbnRpYWxpdHkvb2xkL05aMTMxX3QwX2Vzc2VudGlhbGl0eS5vdXQiLCBza2lwPTcsIGhlYWRlcj1UUlVFKQpuel90MSA9IHJlYWQudGFibGUoImRhdGEvZXNzZW50aWFsaXR5L29sZC9OWjEzMV90MV9lc3NlbnRpYWxpdHkub3V0Iiwgc2tpcD03LCBoZWFkZXI9VFJVRSkKbnpfdDIgPSByZWFkLnRhYmxlKCJkYXRhL2Vzc2VudGlhbGl0eS9vbGQvTloxMzFfdDJfZXNzZW50aWFsaXR5Lm91dCIsIHNraXA9NywgaGVhZGVyPVRSVUUpCm56X3QzID0gcmVhZC50YWJsZSgiZGF0YS9lc3NlbnRpYWxpdHkvb2xkL05aMTMxX3QzX2Vzc2VudGlhbGl0eS5vdXQiLCBza2lwPTcsIGhlYWRlcj1UUlVFKQphbGFiYW1hX2Vzc2VudGlhbHMgPSBtZXJnZShhbGFiYW1hX3QwLCBhbGFiYW1hX3QxLCBieS54PSJPcmYiLCBieS55PSJPcmYiKQphbGFiYW1hX2Vzc2VudGlhbHMgPSBtZXJnZShhbGFiYW1hX2Vzc2VudGlhbHMsIGFsYWJhbWFfdDIsIGJ5Lng9Ik9yZiIsIGJ5Lnk9Ik9yZiIpCmFsYWJhbWFfZXNzZW50aWFscyA9IG1lcmdlKGFsYWJhbWFfZXNzZW50aWFscywgYWxhYmFtYV90MywgYnkueD0iT3JmIiwgYnkueT0iT3JmIikKbnpfZXNzZW50aWFscyA9IG1lcmdlKG56X3QwLCBuel90MSwgYnkueD0iT3JmIiwgYnkueT0iT3JmIikKbnpfZXNzZW50aWFscyA9IG1lcmdlKG56X2Vzc2VudGlhbHMsIG56X3QyLCBieS54PSJPcmYiLCBieS55PSJPcmYiKQpuel9lc3NlbnRpYWxzID0gbWVyZ2UobnpfZXNzZW50aWFscywgbnpfdDMsIGJ5Lng9Ik9yZiIsIGJ5Lnk9Ik9yZiIpCmhlYWQobnpfZXNzZW50aWFscykKClhMQ29ubmVjdDo6Y3JlYXRlU2hlZXQod29ya2Jvb2ssIG5hbWU9ImFsYWJhbWFfZXNzZW50aWFsaXR5IikKWExDb25uZWN0Ojp3cml0ZVdvcmtzaGVldCh3b3JrYm9vaywgYWxhYmFtYV9lc3NlbnRpYWxzLCBzaGVldD0iYWxhYmFtYV9lc3NlbnRpYWxpdHkiKQpYTENvbm5lY3Q6OnNhdmVXb3JrYm9vayh3b3JrYm9vaykKWExDb25uZWN0OjpjcmVhdGVTaGVldCh3b3JrYm9vaywgbmFtZT0ibnoxMzFfZXNzZW50aWFsaXR5IikKWExDb25uZWN0Ojp3cml0ZVdvcmtzaGVldCh3b3JrYm9vaywgbnpfZXNzZW50aWFscywgc2hlZXQ9Im56MTMxX2Vzc2VudGlhbGl0eSIpClhMQ29ubmVjdDo6c2F2ZVdvcmtib29rKHdvcmtib29rKQpgYGAKCiMgUmV0dXJuCgpbbGFzdF0oY2JjYlNFUS5odG1sKSwKPGEgaHJlZj0iIyIgb25jbGljaz0iaGlzdG9yeS5nbygtMSkiPmdvIGJhY2s8L2E+LApbaW5kZXhdKGluZGV4Lmh0bWwpLCBbbmV4dF0oZXNzZW50aWFsaXR5Lmh0bWwpCgpgYGB7ciBydW5fZGF0ZSwgcmVzdWx0cz0nYXNpcycsIGVjaG89RkFMU0V9CmVtYWlsID0gIjxhIGhyZWY9J21haWx0bzphYmVsZXdAdW1kLmVkdSc+QXNodG9uIFRyZXkgQmVsZXc8L2E+IgpsYXN0X3VwZGF0ZSA9IGZvcm1hdChTeXMudGltZSgpLCAiKDx0aW1lPiVZLSVtLSVkPC90aW1lPikiKQpjYXQocGFzdGUoZW1haWwsIGxhc3RfdXBkYXRlKSkKYGBgCgpgYGB7ciBzYXZlLCBpbmNsdWRlPUZBTFNFfQpzYXZlKGxpc3QgPSBscyhhbGw9VFJVRSksIGZpbGUgPSAiUkRhdGEiKQpgYGAK