index.html preprocessing.html

1 Annotation version: 20171102

Any annotation data will need to come from our trinotate information… An interesting caveat, kallisto uses a transcript database. tximport is the library used to read the counts/transcript into R, it is able to take a set oF mappings between gene/transcript in order to provide gene counts rather than transcript.

putative_annotations <- load_trinotate_annotations("reference/trinotate.csv")
annot_by_tx <- putative_annotations
rownames(annot_by_tx) <- make.names(putative_annotations[["transcript_id"]], unique=TRUE)

## I split the annotations into one set keyed by gene IDs and one by transcript IDs.
## This way it is possible to make an expressionset of transcripts or genes by
## removing/keeping the tx_gene_map argument.

## Why would you want to do this? you might ask...  Well, sadly the annotation database
## Does not always have filled-in data for the first transcript for a given gene ID,
## therefore the annotation information for those genes will be lost when we merge
## the count tables / annotation tables by gene ID.
## This is of course also true for transcript IDs, but for a vastly smaller number of them.
transcript_gene_map <- putative_annotations[, c("transcript_id", "gene_id")]
k10tx_raw <- create_expt(metadata="sample_sheets/all_samples.xlsx",
                         gene_info=annot_by_tx)
## Reading the sample metadata.
## The sample definitions comprises: 10, 7 rows, columns.
## Reading count tables.
## Finished reading count tables.
## Matched 234330 annotations and counts.
## Bringing together the count matrix and gene information.
putative_annotations <- fData(k10tx_raw)  ## A cheap way to get back the unique gene IDs.
dim(exprs(k10tx_raw))
## [1] 234330     10
## On further examination, we decided to remove both samples 1003 and 1008
## which Sandra pointed out are in fact from the same flow cytometry isolation.
k8tx_raw <- create_expt(metadata="sample_sheets/kept_samples.xlsx",
                        gene_info=annot_by_tx)
## Reading the sample metadata.
## The sample definitions comprises: 8, 7 rows, columns.
## Reading count tables.
## Finished reading count tables.
## Matched 234330 annotations and counts.
## Bringing together the count matrix and gene information.
dim(exprs(k8tx_raw))
## [1] 234330      8
## If we do not use the tx_gene_map information, we get 234,330 transcripts in the data set.
## Instead, we get 58,486 genes.

## Perform a count/gene cutoff here
threshold <- 4
method <- "cbcb"  ## other methods include 'genefilter' and 'simple'
k10tx_count <- sm(normalize_expt(k10tx_raw, filter=method, thresh=threshold))
dim(exprs(k10tx_count))
## [1] 42143    10
k8tx_count <- sm(normalize_expt(k8tx_raw, filter=method, thresh=threshold))
dim(exprs(k8tx_count))
## [1] 38571     8
## First get rid of the rRNA
sb_rrna <- putative_annotations[["rrna_subunit"]] != ""
rrna_droppers <- rownames(putative_annotations)[sb_rrna]
k10tx_norrna <- exclude_genes_expt(expt=k10tx_raw, ids=rrna_droppers)
## Before removal, there were 234330 entries.
## Now there are 234309 entries.
## Percent kept: 99.990, 99.988, 99.991, 99.993, 99.992, 99.989, 99.989, 99.987, 99.993, 99.995
## Percent removed: 0.010, 0.012, 0.009, 0.007, 0.008, 0.011, 0.011, 0.013, 0.007, 0.005
k8tx_norrna <- exclude_genes_expt(expt=k8tx_raw, ids=rrna_droppers)
## Before removal, there were 234330 entries.
## Now there are 234309 entries.
## Percent kept: 99.990, 99.988, 99.991, 99.992, 99.989, 99.989, 99.987, 99.995
## Percent removed: 0.010, 0.012, 0.009, 0.008, 0.011, 0.011, 0.013, 0.005
## Keep only the blastx hits with a low e-value and high identity.
filtered_keepers <- putative_annotations[["blastx_evalue"]] <= 1e-10 &
  putative_annotations[["blastx_identity"]] >= 60
keepers <- rownames(putative_annotations)[filtered_keepers]
## This excludes all but 33,451 transcripts.

## Now keep only those transcript IDs which fall into the above categories.
k10tx_conf <- exclude_genes_expt(expt=k10tx_norrna, ids=keepers, method="keep")
## Before removal, there were 234309 entries.
## Now there are 33451 entries.
## Percent kept: 25.523, 25.012, 26.033, 25.603, 26.420, 26.603, 27.573, 24.233, 24.821, 27.304
## Percent removed: 74.477, 74.988, 73.967, 74.397, 73.580, 73.397, 72.427, 75.767, 75.179, 72.696
dim(exprs(k10tx_conf))
## [1] 33451    10
k8tx_conf <- exclude_genes_expt(expt=k8tx_norrna, ids=keepers, method="keep")
## Before removal, there were 234309 entries.
## Now there are 33451 entries.
## Percent kept: 25.523, 25.012, 26.033, 26.420, 26.603, 27.573, 24.233, 27.304
## Percent removed: 74.477, 74.988, 73.967, 73.580, 73.397, 72.427, 75.767, 72.696
dim(exprs(k8tx_conf))
## [1] 33451     8
## Perform both the confidence and count filtration
k10tx_conf_count <- sm(normalize_expt(k10tx_conf, filter=method, thresh=threshold))
dim(exprs(k10tx_conf_count))
## [1] 18018    10
k8tx_conf_count <- sm(normalize_expt(k8tx_conf, filter=method, thresh=threshold))
dim(exprs(k8tx_conf_count))
## [1] 16826     8
rrnatx_expt <- exclude_genes_expt(expt=k10tx_raw, ids=sb_rrna, method="keep")
## Before removal, there were 234330 entries.
## Now there are 21 entries.
## Percent kept: 0.010, 0.012, 0.009, 0.007, 0.008, 0.011, 0.011, 0.013, 0.007, 0.005
## Percent removed: 99.990, 99.988, 99.991, 99.993, 99.992, 99.989, 99.989, 99.987, 99.993, 99.995
## This has only 21 putative rRNA transcripts.

2 Plot changes in number oF putative genes

genes_by_subset <- data.frame(
  samples = c(rep("ten", 4), rep("eight", 4)),
  colors = c(rep("#1B9E77", 4), rep("#7570B3", 4)),
  alpha = c("#1B9E77FF", "#1B9E77CC", "#1B0E77AA",
            "#1B0E7777", "#7570B3FF", "#7570B3CC", "#7570B3AA", "#7570B377"),
  type = rep(c("raw", "count", "conf", "conf_count"), 2),
  genes = c(nrow(exprs(k10tx_raw)), nrow(exprs(k10tx_count)),
            nrow(exprs(k10tx_conf)), nrow(exprs(k10tx_conf_count)),
            nrow(exprs(k8tx_raw)), nrow(exprs(k8tx_count)),
            nrow(exprs(k8tx_conf)), nrow(exprs(k8tx_conf_count))))

library(ggplot2)
columns <- ggplot(genes_by_subset, aes(x=samples, y=genes)) +
  geom_col(position="identity", aes(fill=colors, alpha=alpha), color="black") +
  scale_fill_manual(values=c(levels(as.factor(genes_by_subset$colors)))) +
  theme(axis.text=ggplot2::element_text(size=10, colour="black"),
        axis.text.x=ggplot2::element_text(angle=90, vjust=0.5),
        legend.position="none")
columns

c1 <- genes_by_subset[["samples"]] == "ten"
c2 <- genes_by_subset[["samples"]] == "eight"
tmp <- cbind(genes_by_subset[c1, "genes"], genes_by_subset[c2, "genes"])
colnames(tmp) <- c("ten", "eight")
rownames(tmp) <- c("raw", "count", "conf", "conf_count")
tmp
##               ten  eight
## raw        234330 234330
## count       42143  38571
## conf        33451  33451
## conf_count  18018  16826
pander::pander(sessionInfo())

R version 3.4.4 RC (2018-03-09 r74380)

**Platform:** x86_64-pc-linux-gnu (64-bit)

locale: LC_CTYPE=en_US.utf8, LC_NUMERIC=C, LC_TIME=en_US.utf8, LC_COLLATE=en_US.utf8, LC_MONETARY=en_US.utf8, LC_MESSAGES=en_US.utf8, LC_PAPER=en_US.utf8, LC_NAME=C, LC_ADDRESS=C, LC_TELEPHONE=C, LC_MEASUREMENT=en_US.utf8 and LC_IDENTIFICATION=C

attached base packages: stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: ggplot2(v.2.2.1) and hpgltools(v.2018.03)

loaded via a namespace (and not attached): Rcpp(v.0.12.15), RColorBrewer(v.1.1-2), bindr(v.0.1.1), pillar(v.1.2.1), compiler(v.3.4.4), plyr(v.1.8.4), zlibbioc(v.1.24.0), base64enc(v.0.1-3), iterators(v.1.0.9), tools(v.3.4.4), digest(v.0.6.15), rhdf5(v.2.22.0), evaluate(v.0.10.1), memoise(v.1.1.0), tibble(v.1.4.2), gtable(v.0.2.0), pkgconfig(v.2.0.1), rlang(v.0.2.0), openxlsx(v.4.0.17), foreach(v.1.4.4), commonmark(v.1.4), yaml(v.2.1.18), parallel(v.3.4.4), bindrcpp(v.0.2), dplyr(v.0.7.4), withr(v.2.1.1), stringr(v.1.3.0), knitr(v.1.20), roxygen2(v.6.0.1), xml2(v.1.2.0), hms(v.0.4.2), devtools(v.1.13.5), tidyselect(v.0.2.4), rprojroot(v.1.3-2), grid(v.3.4.4), glue(v.1.2.0), data.table(v.1.10.4-3), Biobase(v.2.38.0), R6(v.2.2.2), rmarkdown(v.1.9), pander(v.0.6.1), readr(v.1.1.1), purrr(v.0.2.4), tidyr(v.0.8.0), magrittr(v.1.5), scales(v.0.5.0), backports(v.1.1.2), codetools(v.0.2-15), htmltools(v.0.3.6), BiocGenerics(v.0.24.0), tximport(v.1.6.0), assertthat(v.0.2.0), colorspace(v.1.3-2), labeling(v.0.3), stringi(v.1.1.7), lazyeval(v.0.2.1) and munsell(v.0.4.3)

message(paste0("This is hpgltools commit: ", get_git_commit()))
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset e3a7f13d63d6906d825dbfad37273ddd71e44e86
## R> packrat::restore()
## This is hpgltools commit: Mon Mar 12 12:11:17 2018 -0400: e3a7f13d63d6906d825dbfad37273ddd71e44e86
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
## Saving to 01_annotation_tx-v20171102.rda.xz
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiU29sYW51bSBiZXRhY2V1bSBhbm5vdGF0aW9uIGRhdGEiCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShocGdsdG9vbHMpCnR0IDwtIGRldnRvb2xzOjpsb2FkX2FsbCgifi9ocGdsdG9vbHMiKQprbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICB2ZXJib3NlPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgIHdpZHRoPTkwLAogICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCmtuaXRyOjpvcHRzX2NodW5rJHNldChlcnJvcj1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLndpZHRoPTgsCiAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICBkcGk9OTYpCm9sZF9vcHRpb25zIDwtIG9wdGlvbnMoZGlnaXRzPTQsCiAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICBrbml0ci5kdXBsaWNhdGUubGFiZWw9ImFsbG93IikKZ2dwbG90Mjo6dGhlbWVfc2V0KGdncGxvdDI6OnRoZW1lX2J3KGJhc2Vfc2l6ZT0xMCkpCnNldC5zZWVkKDEpCnZlciA8LSAiMjAxNzExMDIiCnByZXZpb3VzX2ZpbGUgPC0gImluZGV4LlJtZCIKCnRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpKQpybWRfZmlsZSA8LSAiMDFfYW5ub3RhdGlvbl90eC5SbWQiCmBgYAoKW2luZGV4Lmh0bWxdKGluZGV4Lmh0bWwpIFtwcmVwcm9jZXNzaW5nLmh0bWxdKHByZXByb2Nlc3NpbmcuaHRtbCkKCiMgQW5ub3RhdGlvbiB2ZXJzaW9uOiBgciB2ZXJgCgpBbnkgYW5ub3RhdGlvbiBkYXRhIHdpbGwgbmVlZCB0byBjb21lIGZyb20gb3VyIHRyaW5vdGF0ZSBpbmZvcm1hdGlvbi4uLgpBbiBpbnRlcmVzdGluZyBjYXZlYXQsIGthbGxpc3RvIHVzZXMgYSB0cmFuc2NyaXB0IGRhdGFiYXNlLiAgdHhpbXBvcnQgaXMgdGhlIGxpYnJhcnkKdXNlZCB0byByZWFkIHRoZSBjb3VudHMvdHJhbnNjcmlwdCBpbnRvIFIsIGl0IGlzIGFibGUgdG8gdGFrZSBhIHNldCBvRiBtYXBwaW5ncyBiZXR3ZWVuCmdlbmUvdHJhbnNjcmlwdCBpbiBvcmRlciB0byBwcm92aWRlIGdlbmUgY291bnRzIHJhdGhlciB0aGFuIHRyYW5zY3JpcHQuCgpgYGB7ciBhbm5vdGF0aW9ufQpwdXRhdGl2ZV9hbm5vdGF0aW9ucyA8LSBsb2FkX3RyaW5vdGF0ZV9hbm5vdGF0aW9ucygicmVmZXJlbmNlL3RyaW5vdGF0ZS5jc3YiKQphbm5vdF9ieV90eCA8LSBwdXRhdGl2ZV9hbm5vdGF0aW9ucwpyb3duYW1lcyhhbm5vdF9ieV90eCkgPC0gbWFrZS5uYW1lcyhwdXRhdGl2ZV9hbm5vdGF0aW9uc1tbInRyYW5zY3JpcHRfaWQiXV0sIHVuaXF1ZT1UUlVFKQoKIyMgSSBzcGxpdCB0aGUgYW5ub3RhdGlvbnMgaW50byBvbmUgc2V0IGtleWVkIGJ5IGdlbmUgSURzIGFuZCBvbmUgYnkgdHJhbnNjcmlwdCBJRHMuCiMjIFRoaXMgd2F5IGl0IGlzIHBvc3NpYmxlIHRvIG1ha2UgYW4gZXhwcmVzc2lvbnNldCBvZiB0cmFuc2NyaXB0cyBvciBnZW5lcyBieQojIyByZW1vdmluZy9rZWVwaW5nIHRoZSB0eF9nZW5lX21hcCBhcmd1bWVudC4KCiMjIFdoeSB3b3VsZCB5b3Ugd2FudCB0byBkbyB0aGlzPyB5b3UgbWlnaHQgYXNrLi4uICBXZWxsLCBzYWRseSB0aGUgYW5ub3RhdGlvbiBkYXRhYmFzZQojIyBEb2VzIG5vdCBhbHdheXMgaGF2ZSBmaWxsZWQtaW4gZGF0YSBmb3IgdGhlIGZpcnN0IHRyYW5zY3JpcHQgZm9yIGEgZ2l2ZW4gZ2VuZSBJRCwKIyMgdGhlcmVmb3JlIHRoZSBhbm5vdGF0aW9uIGluZm9ybWF0aW9uIGZvciB0aG9zZSBnZW5lcyB3aWxsIGJlIGxvc3Qgd2hlbiB3ZSBtZXJnZQojIyB0aGUgY291bnQgdGFibGVzIC8gYW5ub3RhdGlvbiB0YWJsZXMgYnkgZ2VuZSBJRC4KIyMgVGhpcyBpcyBvZiBjb3Vyc2UgYWxzbyB0cnVlIGZvciB0cmFuc2NyaXB0IElEcywgYnV0IGZvciBhIHZhc3RseSBzbWFsbGVyIG51bWJlciBvZiB0aGVtLgp0cmFuc2NyaXB0X2dlbmVfbWFwIDwtIHB1dGF0aXZlX2Fubm90YXRpb25zWywgYygidHJhbnNjcmlwdF9pZCIsICJnZW5lX2lkIildCmsxMHR4X3JhdyA8LSBjcmVhdGVfZXhwdChtZXRhZGF0YT0ic2FtcGxlX3NoZWV0cy9hbGxfc2FtcGxlcy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfaW5mbz1hbm5vdF9ieV90eCkKcHV0YXRpdmVfYW5ub3RhdGlvbnMgPC0gZkRhdGEoazEwdHhfcmF3KSAgIyMgQSBjaGVhcCB3YXkgdG8gZ2V0IGJhY2sgdGhlIHVuaXF1ZSBnZW5lIElEcy4KZGltKGV4cHJzKGsxMHR4X3JhdykpCiMjIE9uIGZ1cnRoZXIgZXhhbWluYXRpb24sIHdlIGRlY2lkZWQgdG8gcmVtb3ZlIGJvdGggc2FtcGxlcyAxMDAzIGFuZCAxMDA4CiMjIHdoaWNoIFNhbmRyYSBwb2ludGVkIG91dCBhcmUgaW4gZmFjdCBmcm9tIHRoZSBzYW1lIGZsb3cgY3l0b21ldHJ5IGlzb2xhdGlvbi4Kazh0eF9yYXcgPC0gY3JlYXRlX2V4cHQobWV0YWRhdGE9InNhbXBsZV9zaGVldHMva2VwdF9zYW1wbGVzLnhsc3giLAogICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89YW5ub3RfYnlfdHgpCmRpbShleHBycyhrOHR4X3JhdykpCiMjIElmIHdlIGRvIG5vdCB1c2UgdGhlIHR4X2dlbmVfbWFwIGluZm9ybWF0aW9uLCB3ZSBnZXQgMjM0LDMzMCB0cmFuc2NyaXB0cyBpbiB0aGUgZGF0YSBzZXQuCiMjIEluc3RlYWQsIHdlIGdldCA1OCw0ODYgZ2VuZXMuCgojIyBQZXJmb3JtIGEgY291bnQvZ2VuZSBjdXRvZmYgaGVyZQp0aHJlc2hvbGQgPC0gNAptZXRob2QgPC0gImNiY2IiICAjIyBvdGhlciBtZXRob2RzIGluY2x1ZGUgJ2dlbmVmaWx0ZXInIGFuZCAnc2ltcGxlJwprMTB0eF9jb3VudCA8LSBzbShub3JtYWxpemVfZXhwdChrMTB0eF9yYXcsIGZpbHRlcj1tZXRob2QsIHRocmVzaD10aHJlc2hvbGQpKQpkaW0oZXhwcnMoazEwdHhfY291bnQpKQprOHR4X2NvdW50IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGs4dHhfcmF3LCBmaWx0ZXI9bWV0aG9kLCB0aHJlc2g9dGhyZXNob2xkKSkKZGltKGV4cHJzKGs4dHhfY291bnQpKQoKIyMgRmlyc3QgZ2V0IHJpZCBvZiB0aGUgclJOQQpzYl9ycm5hIDwtIHB1dGF0aXZlX2Fubm90YXRpb25zW1sicnJuYV9zdWJ1bml0Il1dICE9ICIiCnJybmFfZHJvcHBlcnMgPC0gcm93bmFtZXMocHV0YXRpdmVfYW5ub3RhdGlvbnMpW3NiX3JybmFdCmsxMHR4X25vcnJuYSA8LSBleGNsdWRlX2dlbmVzX2V4cHQoZXhwdD1rMTB0eF9yYXcsIGlkcz1ycm5hX2Ryb3BwZXJzKQprOHR4X25vcnJuYSA8LSBleGNsdWRlX2dlbmVzX2V4cHQoZXhwdD1rOHR4X3JhdywgaWRzPXJybmFfZHJvcHBlcnMpCgojIyBLZWVwIG9ubHkgdGhlIGJsYXN0eCBoaXRzIHdpdGggYSBsb3cgZS12YWx1ZSBhbmQgaGlnaCBpZGVudGl0eS4KZmlsdGVyZWRfa2VlcGVycyA8LSBwdXRhdGl2ZV9hbm5vdGF0aW9uc1tbImJsYXN0eF9ldmFsdWUiXV0gPD0gMWUtMTAgJgogIHB1dGF0aXZlX2Fubm90YXRpb25zW1siYmxhc3R4X2lkZW50aXR5Il1dID49IDYwCmtlZXBlcnMgPC0gcm93bmFtZXMocHV0YXRpdmVfYW5ub3RhdGlvbnMpW2ZpbHRlcmVkX2tlZXBlcnNdCiMjIFRoaXMgZXhjbHVkZXMgYWxsIGJ1dCAzMyw0NTEgdHJhbnNjcmlwdHMuCgojIyBOb3cga2VlcCBvbmx5IHRob3NlIHRyYW5zY3JpcHQgSURzIHdoaWNoIGZhbGwgaW50byB0aGUgYWJvdmUgY2F0ZWdvcmllcy4KazEwdHhfY29uZiA8LSBleGNsdWRlX2dlbmVzX2V4cHQoZXhwdD1rMTB0eF9ub3JybmEsIGlkcz1rZWVwZXJzLCBtZXRob2Q9ImtlZXAiKQpkaW0oZXhwcnMoazEwdHhfY29uZikpCms4dHhfY29uZiA8LSBleGNsdWRlX2dlbmVzX2V4cHQoZXhwdD1rOHR4X25vcnJuYSwgaWRzPWtlZXBlcnMsIG1ldGhvZD0ia2VlcCIpCmRpbShleHBycyhrOHR4X2NvbmYpKQoKIyMgUGVyZm9ybSBib3RoIHRoZSBjb25maWRlbmNlIGFuZCBjb3VudCBmaWx0cmF0aW9uCmsxMHR4X2NvbmZfY291bnQgPC0gc20obm9ybWFsaXplX2V4cHQoazEwdHhfY29uZiwgZmlsdGVyPW1ldGhvZCwgdGhyZXNoPXRocmVzaG9sZCkpCmRpbShleHBycyhrMTB0eF9jb25mX2NvdW50KSkKazh0eF9jb25mX2NvdW50IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGs4dHhfY29uZiwgZmlsdGVyPW1ldGhvZCwgdGhyZXNoPXRocmVzaG9sZCkpCmRpbShleHBycyhrOHR4X2NvbmZfY291bnQpKQoKcnJuYXR4X2V4cHQgPC0gZXhjbHVkZV9nZW5lc19leHB0KGV4cHQ9azEwdHhfcmF3LCBpZHM9c2JfcnJuYSwgbWV0aG9kPSJrZWVwIikKIyMgVGhpcyBoYXMgb25seSAyMSBwdXRhdGl2ZSByUk5BIHRyYW5zY3JpcHRzLgpgYGAKCiMgUGxvdCBjaGFuZ2VzIGluIG51bWJlciBvRiBwdXRhdGl2ZSBnZW5lcwoKYGBge3IgcHV0YXRpdmVfZ2VuZXN9CmdlbmVzX2J5X3N1YnNldCA8LSBkYXRhLmZyYW1lKAogIHNhbXBsZXMgPSBjKHJlcCgidGVuIiwgNCksIHJlcCgiZWlnaHQiLCA0KSksCiAgY29sb3JzID0gYyhyZXAoIiMxQjlFNzciLCA0KSwgcmVwKCIjNzU3MEIzIiwgNCkpLAogIGFscGhhID0gYygiIzFCOUU3N0ZGIiwgIiMxQjlFNzdDQyIsICIjMUIwRTc3QUEiLAogICAgICAgICAgICAiIzFCMEU3Nzc3IiwgIiM3NTcwQjNGRiIsICIjNzU3MEIzQ0MiLCAiIzc1NzBCM0FBIiwgIiM3NTcwQjM3NyIpLAogIHR5cGUgPSByZXAoYygicmF3IiwgImNvdW50IiwgImNvbmYiLCAiY29uZl9jb3VudCIpLCAyKSwKICBnZW5lcyA9IGMobnJvdyhleHBycyhrMTB0eF9yYXcpKSwgbnJvdyhleHBycyhrMTB0eF9jb3VudCkpLAogICAgICAgICAgICBucm93KGV4cHJzKGsxMHR4X2NvbmYpKSwgbnJvdyhleHBycyhrMTB0eF9jb25mX2NvdW50KSksCiAgICAgICAgICAgIG5yb3coZXhwcnMoazh0eF9yYXcpKSwgbnJvdyhleHBycyhrOHR4X2NvdW50KSksCiAgICAgICAgICAgIG5yb3coZXhwcnMoazh0eF9jb25mKSksIG5yb3coZXhwcnMoazh0eF9jb25mX2NvdW50KSkpKQoKbGlicmFyeShnZ3Bsb3QyKQpjb2x1bW5zIDwtIGdncGxvdChnZW5lc19ieV9zdWJzZXQsIGFlcyh4PXNhbXBsZXMsIHk9Z2VuZXMpKSArCiAgZ2VvbV9jb2wocG9zaXRpb249ImlkZW50aXR5IiwgYWVzKGZpbGw9Y29sb3JzLCBhbHBoYT1hbHBoYSksIGNvbG9yPSJibGFjayIpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YyhsZXZlbHMoYXMuZmFjdG9yKGdlbmVzX2J5X3N1YnNldCRjb2xvcnMpKSkpICsKICB0aGVtZShheGlzLnRleHQ9Z2dwbG90Mjo6ZWxlbWVudF90ZXh0KHNpemU9MTAsIGNvbG91cj0iYmxhY2siKSwKICAgICAgICBheGlzLnRleHQueD1nZ3Bsb3QyOjplbGVtZW50X3RleHQoYW5nbGU9OTAsIHZqdXN0PTAuNSksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uPSJub25lIikKY29sdW1ucwpjMSA8LSBnZW5lc19ieV9zdWJzZXRbWyJzYW1wbGVzIl1dID09ICJ0ZW4iCmMyIDwtIGdlbmVzX2J5X3N1YnNldFtbInNhbXBsZXMiXV0gPT0gImVpZ2h0Igp0bXAgPC0gY2JpbmQoZ2VuZXNfYnlfc3Vic2V0W2MxLCAiZ2VuZXMiXSwgZ2VuZXNfYnlfc3Vic2V0W2MyLCAiZ2VuZXMiXSkKY29sbmFtZXModG1wKSA8LSBjKCJ0ZW4iLCAiZWlnaHQiKQpyb3duYW1lcyh0bXApIDwtIGMoInJhdyIsICJjb3VudCIsICJjb25mIiwgImNvbmZfY291bnQiKQp0bXAKYGBgCgpgYGB7ciBzYXZlbWV9CnBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCm1lc3NhZ2UocGFzdGUwKCJUaGlzIGlzIGhwZ2x0b29scyBjb21taXQ6ICIsIGdldF9naXRfY29tbWl0KCkpKQp0aGlzX3NhdmUgPC0gcGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1ybWRfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKQptZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkpCnRtcCA8LSBzbShzYXZlbWUoZmlsZW5hbWU9dGhpc19zYXZlKSkKYGBgCg==