1 Annotation version: 20171102

Any annotation data will need to come from our trinotate result. 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.

An important aspect of using trinity for this creation of our annotation data: there are many putative transcripts for each putative gene, many of which are probably not real, but instead are artifacts of the assembler. Therefore we need to do something to try to distinguish between the reals and fakers. The following code will attempt to address this problem.

1.1 Load all trinotate data

putative_annotations <- sm(load_trinotate_annotations("reference/trinotate.csv"))
annot_by_gene <- putative_annotations
## Let us make one set of annotations by transcript ID and one by gene ID
rownames(annot_by_gene) <- make.names(putative_annotations[["gene_id"]], unique=TRUE)
annot_by_tx <- putative_annotations
rownames(annot_by_tx) <- make.names(putative_annotations[["transcript_id"]], unique=TRUE)

1.2 Create the expressionsets

In order to make functional expressionsets of this data, we will need to use the mappings from gene <-> transcripts, that is the final argument to create_expt().

## 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")]
k10_raw <- create_expt(metadata="sample_sheets/all_samples.xlsx",
                       gene_info=annot_by_gene,
                       tx_gene_map=transcript_gene_map)
## Reading the sample metadata.
## The sample definitions comprises: 10, 7 rows, columns.
## Reading count tables.
## Using the transcript<->gene mapping.
## Finished reading count tables.
## Matched 58486 annotations and counts.
## Bringing together the count matrix and gene information.
putative_annotations <- fData(k10_raw)  ## A cheap way to get back the unique gene IDs.
## 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.
k8_raw <- create_expt(metadata="sample_sheets/kept_samples.xlsx",
                      gene_info=annot_by_gene,
                      tx_gene_map=transcript_gene_map)
## Reading the sample metadata.
## The sample definitions comprises: 8, 7 rows, columns.
## Reading count tables.
## Using the transcript<->gene mapping.
## Finished reading count tables.
## Matched 58486 annotations and counts.
## Bringing together the count matrix and gene information.
## 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.

1.2.1 How many putative features in the raw data?

dim(exprs(k10_raw))
## [1] 58486    10
dim(exprs(k8_raw))
## [1] 58486     8

1.3 Threshold cutoff

Start by dropping all features with less than 4 counts across all samples. This should get rid of a significant number of the false positive transcripts. While I am at it, I will drop the features annotated as rRNA.

## Perform a count/gene cutoff here
threshold <- 4
method <- "cbcb"  ## other methods include 'genefilter' and 'simple'
k10_count <- sm(normalize_expt(k10_raw, filter=method, thresh=threshold))
k8_count <- sm(normalize_expt(k8_raw, filter=method, thresh=threshold))

## First get rid of the rRNA
sb_rrna <- putative_annotations[["rrna_subunit"]] != ""
rrna_droppers <- rownames(putative_annotations)[sb_rrna]
k10_norrna <- exclude_genes_expt(expt=k10_raw, ids=rrna_droppers)
## Before removal, there were 58486 entries.
## Now there are 58481 entries.
## Percent kept: 99.994, 99.994, 99.994, 99.996, 99.996, 99.993, 99.991, 99.994, 99.996, 99.995
## Percent removed: 0.006, 0.006, 0.006, 0.004, 0.004, 0.007, 0.009, 0.006, 0.004, 0.005
k8_norrna <- exclude_genes_expt(expt=k8_raw, ids=rrna_droppers)
## Before removal, there were 58486 entries.
## Now there are 58481 entries.
## Percent kept: 99.994, 99.994, 99.994, 99.996, 99.993, 99.991, 99.994, 99.995
## Percent removed: 0.006, 0.006, 0.006, 0.004, 0.007, 0.009, 0.006, 0.005

1.3.1 How many high-count features are in the data?

dim(exprs(k10_count))
## [1] 24132    10
dim(exprs(k8_count))
## [1] 23211     8

1.4 Confidence cutoff

Now lets drop those features for which we have relatively lower confidence in the BLAST results from trinotate.

## 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.
k10_conf <- exclude_genes_expt(expt=k10_norrna, ids=keepers, method="keep")
## Before removal, there were 58481 entries.
## Now there are 4888 entries.
## Percent kept: 23.611, 22.922, 24.308, 23.931, 24.798, 24.603, 25.471, 22.574, 23.289, 25.368
## Percent removed: 76.389, 77.078, 75.692, 76.069, 75.202, 75.397, 74.529, 77.426, 76.711, 74.632
k8_conf <- exclude_genes_expt(expt=k8_norrna, ids=keepers, method="keep")
## Before removal, there were 58481 entries.
## Now there are 4888 entries.
## Percent kept: 23.611, 22.922, 24.308, 24.798, 24.603, 25.471, 22.574, 25.368
## Percent removed: 76.389, 77.078, 75.692, 75.202, 75.397, 74.529, 77.426, 74.632

1.5 How many high-confidence features are in the data?

dim(exprs(k10_conf))
## [1] 4888   10
dim(exprs(k8_conf))
## [1] 4888    8

1.6 Both cutoffs

Finally, lets be super-strict and remove both.

## Perform both the confidence and count filtration
k10_conf_count <- sm(normalize_expt(k10_conf, filter=method, thresh=threshold))
k8_conf_count <- sm(normalize_expt(k8_conf, filter=method, thresh=threshold))

rrna_expt <- exclude_genes_expt(expt=k10_raw, ids=sb_rrna, method="keep")
## Before removal, there were 58486 entries.
## Now there are 5 entries.
## Percent kept: 0.006, 0.006, 0.006, 0.004, 0.004, 0.007, 0.009, 0.006, 0.004, 0.005
## Percent removed: 99.994, 99.994, 99.994, 99.996, 99.996, 99.993, 99.991, 99.994, 99.996, 99.995
## This has only 21 putative rRNA transcripts.

1.6.1 How many high-count and high-confidence features?

dim(exprs(k10_conf_count))
## [1] 4392   10
dim(exprs(k8_conf_count))
## [1] 4328    8

2 Plot changes in number of putative genes

There are a few ways to visualize the changes wrought in the data by these operations. Here are two bar plots which attempt to show what happened, the first stacks the relatively-sized library sizes atop one another, the second stacks them on the x-axis.

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(k10_raw)), nrow(exprs(k10_count)),
            nrow(exprs(k10_conf)), nrow(exprs(k10_conf_count)),
            nrow(exprs(k8_raw)), nrow(exprs(k8_count)),
            nrow(exprs(k8_conf)), nrow(exprs(k8_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")
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        58486 58486
## count      24132 23211
## conf        4888  4888
## conf_count  4392  4328
pp(file="images/genes_by_columns.png", image=columns)
if (!isTRUE(get0("skip_load"))) {
  pander::pander(sessionInfo())
  message(paste0("This is hpgltools commit: ", get_git_commit()))
  this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
  message(paste0("Saving to ", this_save))
  tmp <- sm(saveme(filename=this_save))
}
## If you wish to reproduce this exact build of hpgltools, invoke the following:
## > git clone http://github.com/abelew/hpgltools.git
## > git reset 2a0661d6e37f8a3d8831eb3bbd6347c0d9c4b3b7
## R> packrat::restore()
## This is hpgltools commit: Thu Mar 29 16:59:07 2018 -0400: 2a0661d6e37f8a3d8831eb3bbd6347c0d9c4b3b7
## Saving to 01_annotation-v20171102.rda.xz
LS0tCnRpdGxlOiAiUy5iZXRhY2V1bSAyMDE3MDg6IGFubm90YXRpb24gZGF0YSIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiBkZWZhdWx0CiAga2VlcF9tZDogZmFsc2UKICBtb2RlOiBzZWxmY29udGFpbmVkCiAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlCiAgc2VsZl9jb250YWluZWQ6IHRydWUKICB0aGVtZTogcmVhZGFibGUKICB0b2M6IHRydWUKICB0b2NfZmxvYXQ6CiAgICBjb2xsYXBzZWQ6IGZhbHNlCiAgICBzbW9vdGhfc2Nyb2xsOiBmYWxzZQotLS0KCjxzdHlsZT4KICBib2R5IC5tYWluLWNvbnRhaW5lciB7CiAgICBtYXgtd2lkdGg6IDE2MDBweDsKICB9Cjwvc3R5bGU+CgpgYGB7ciBvcHRpb25zLCBpbmNsdWRlPUZBTFNFfQppZiAoIWlzVFJVRShnZXQwKCJza2lwX2xvYWQiKSkpIHsKICBsaWJyYXJ5KGhwZ2x0b29scykKICB0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKICBrbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB3aWR0aD05MCwKICAgICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCiAga25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aD04LAogICAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKICBvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQogIGdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQogIHZlciA8LSAiMjAxNzExMDIiCiAgcHJldmlvdXNfZmlsZSA8LSAiaW5kZXguUm1kIgoKICB0bXAgPC0gdHJ5KHNtKGxvYWRtZShmaWxlbmFtZT1wYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXByZXZpb3VzX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikpKSkKICBybWRfZmlsZSA8LSAiMDFfYW5ub3RhdGlvbi5SbWQiCn0KYGBgCgojIEFubm90YXRpb24gdmVyc2lvbjogYHIgdmVyYAoKQW55IGFubm90YXRpb24gZGF0YSB3aWxsIG5lZWQgdG8gY29tZSBmcm9tIG91ciB0cmlub3RhdGUgcmVzdWx0LgpBbiBpbnRlcmVzdGluZyBjYXZlYXQsIGthbGxpc3RvIHVzZXMgYSB0cmFuc2NyaXB0IGRhdGFiYXNlLiAgdHhpbXBvcnQgaXMgdGhlIGxpYnJhcnkKdXNlZCB0byByZWFkIHRoZSBjb3VudHMvdHJhbnNjcmlwdCBpbnRvIFIsIGl0IGlzIGFibGUgdG8gdGFrZSBhIHNldCBvZiBtYXBwaW5ncyBiZXR3ZWVuCmdlbmUvdHJhbnNjcmlwdCBpbiBvcmRlciB0byBwcm92aWRlIGdlbmUgY291bnRzIHJhdGhlciB0aGFuIHRyYW5zY3JpcHQuCgpBbiBpbXBvcnRhbnQgYXNwZWN0IG9mIHVzaW5nIHRyaW5pdHkgZm9yIHRoaXMgY3JlYXRpb24gb2Ygb3VyIGFubm90YXRpb24gZGF0YToKdGhlcmUgYXJlIG1hbnkgcHV0YXRpdmUgdHJhbnNjcmlwdHMgZm9yIGVhY2ggcHV0YXRpdmUgZ2VuZSwgbWFueSBvZiB3aGljaCBhcmUKcHJvYmFibHkgbm90IHJlYWwsIGJ1dCBpbnN0ZWFkIGFyZSBhcnRpZmFjdHMgb2YgdGhlIGFzc2VtYmxlci4gIFRoZXJlZm9yZSB3ZQpuZWVkIHRvIGRvIHNvbWV0aGluZyB0byB0cnkgdG8gZGlzdGluZ3Vpc2ggYmV0d2VlbiB0aGUgcmVhbHMgYW5kIGZha2Vycy4gIFRoZQpmb2xsb3dpbmcgY29kZSB3aWxsIGF0dGVtcHQgdG8gYWRkcmVzcyB0aGlzIHByb2JsZW0uCgojIyBMb2FkIGFsbCB0cmlub3RhdGUgZGF0YQoKYGBge3IgYW5ub3RhdGlvbn0KcHV0YXRpdmVfYW5ub3RhdGlvbnMgPC0gc20obG9hZF90cmlub3RhdGVfYW5ub3RhdGlvbnMoInJlZmVyZW5jZS90cmlub3RhdGUuY3N2IikpCmFubm90X2J5X2dlbmUgPC0gcHV0YXRpdmVfYW5ub3RhdGlvbnMKIyMgTGV0IHVzIG1ha2Ugb25lIHNldCBvZiBhbm5vdGF0aW9ucyBieSB0cmFuc2NyaXB0IElEIGFuZCBvbmUgYnkgZ2VuZSBJRApyb3duYW1lcyhhbm5vdF9ieV9nZW5lKSA8LSBtYWtlLm5hbWVzKHB1dGF0aXZlX2Fubm90YXRpb25zW1siZ2VuZV9pZCJdXSwgdW5pcXVlPVRSVUUpCmFubm90X2J5X3R4IDwtIHB1dGF0aXZlX2Fubm90YXRpb25zCnJvd25hbWVzKGFubm90X2J5X3R4KSA8LSBtYWtlLm5hbWVzKHB1dGF0aXZlX2Fubm90YXRpb25zW1sidHJhbnNjcmlwdF9pZCJdXSwgdW5pcXVlPVRSVUUpCmBgYAoKIyMgQ3JlYXRlIHRoZSBleHByZXNzaW9uc2V0cwoKSW4gb3JkZXIgdG8gbWFrZSBmdW5jdGlvbmFsIGV4cHJlc3Npb25zZXRzIG9mIHRoaXMgZGF0YSwgd2Ugd2lsbCBuZWVkIHRvIHVzZQp0aGUgbWFwcGluZ3MgZnJvbSBnZW5lIDwtPiB0cmFuc2NyaXB0cywgdGhhdCBpcyB0aGUgZmluYWwgYXJndW1lbnQgdG8KY3JlYXRlX2V4cHQoKS4KCmBgYHtyIGNyZWF0ZV9leHB0fQojIyBJIHNwbGl0IHRoZSBhbm5vdGF0aW9ucyBpbnRvIG9uZSBzZXQga2V5ZWQgYnkgZ2VuZSBJRHMgYW5kIG9uZSBieSB0cmFuc2NyaXB0IElEcy4KIyMgVGhpcyB3YXkgaXQgaXMgcG9zc2libGUgdG8gbWFrZSBhbiBleHByZXNzaW9uc2V0IG9mIHRyYW5zY3JpcHRzIG9yIGdlbmVzIGJ5CiMjIHJlbW92aW5nL2tlZXBpbmcgdGhlIHR4X2dlbmVfbWFwIGFyZ3VtZW50LgoKIyMgV2h5IHdvdWxkIHlvdSB3YW50IHRvIGRvIHRoaXM/IHlvdSBtaWdodCBhc2suLi4gIFdlbGwsIHNhZGx5IHRoZSBhbm5vdGF0aW9uIGRhdGFiYXNlCiMjIERvZXMgbm90IGFsd2F5cyBoYXZlIGZpbGxlZC1pbiBkYXRhIGZvciB0aGUgZmlyc3QgdHJhbnNjcmlwdCBmb3IgYSBnaXZlbiBnZW5lIElELAojIyB0aGVyZWZvcmUgdGhlIGFubm90YXRpb24gaW5mb3JtYXRpb24gZm9yIHRob3NlIGdlbmVzIHdpbGwgYmUgbG9zdCB3aGVuIHdlIG1lcmdlCiMjIHRoZSBjb3VudCB0YWJsZXMgLyBhbm5vdGF0aW9uIHRhYmxlcyBieSBnZW5lIElELgojIyBUaGlzIGlzIG9mIGNvdXJzZSBhbHNvIHRydWUgZm9yIHRyYW5zY3JpcHQgSURzLCBidXQgZm9yIGEgdmFzdGx5IHNtYWxsZXIgbnVtYmVyIG9mIHRoZW0uCnRyYW5zY3JpcHRfZ2VuZV9tYXAgPC0gcHV0YXRpdmVfYW5ub3RhdGlvbnNbLCBjKCJ0cmFuc2NyaXB0X2lkIiwgImdlbmVfaWQiKV0KazEwX3JhdyA8LSBjcmVhdGVfZXhwdChtZXRhZGF0YT0ic2FtcGxlX3NoZWV0cy9hbGxfc2FtcGxlcy54bHN4IiwKICAgICAgICAgICAgICAgICAgICAgICBnZW5lX2luZm89YW5ub3RfYnlfZ2VuZSwKICAgICAgICAgICAgICAgICAgICAgICB0eF9nZW5lX21hcD10cmFuc2NyaXB0X2dlbmVfbWFwKQpwdXRhdGl2ZV9hbm5vdGF0aW9ucyA8LSBmRGF0YShrMTBfcmF3KSAgIyMgQSBjaGVhcCB3YXkgdG8gZ2V0IGJhY2sgdGhlIHVuaXF1ZSBnZW5lIElEcy4KIyMgT24gZnVydGhlciBleGFtaW5hdGlvbiwgd2UgZGVjaWRlZCB0byByZW1vdmUgYm90aCBzYW1wbGVzIDEwMDMgYW5kIDEwMDgKIyMgd2hpY2ggU2FuZHJhIHBvaW50ZWQgb3V0IGFyZSBpbiBmYWN0IGZyb20gdGhlIHNhbWUgZmxvdyBjeXRvbWV0cnkgaXNvbGF0aW9uLgprOF9yYXcgPC0gY3JlYXRlX2V4cHQobWV0YWRhdGE9InNhbXBsZV9zaGVldHMva2VwdF9zYW1wbGVzLnhsc3giLAogICAgICAgICAgICAgICAgICAgICAgZ2VuZV9pbmZvPWFubm90X2J5X2dlbmUsCiAgICAgICAgICAgICAgICAgICAgICB0eF9nZW5lX21hcD10cmFuc2NyaXB0X2dlbmVfbWFwKQojIyBJZiB3ZSBkbyBub3QgdXNlIHRoZSB0eF9nZW5lX21hcCBpbmZvcm1hdGlvbiwgd2UgZ2V0IDIzNCwzMzAgdHJhbnNjcmlwdHMgaW4gdGhlIGRhdGEgc2V0LgojIyBJbnN0ZWFkLCB3ZSBnZXQgNTgsNDg2IGdlbmVzLgpgYGAKCiMjIyBIb3cgbWFueSBwdXRhdGl2ZSBmZWF0dXJlcyBpbiB0aGUgcmF3IGRhdGE/CgpgYGB7ciByYXdfZmVhdHVyZXN9CmRpbShleHBycyhrMTBfcmF3KSkKZGltKGV4cHJzKGs4X3JhdykpCmBgYAoKIyMgVGhyZXNob2xkIGN1dG9mZgoKU3RhcnQgYnkgZHJvcHBpbmcgYWxsIGZlYXR1cmVzIHdpdGggbGVzcyB0aGFuIDQgY291bnRzIGFjcm9zcyBhbGwgc2FtcGxlcy4gIFRoaXMKc2hvdWxkIGdldCByaWQgb2YgYSBzaWduaWZpY2FudCBudW1iZXIgb2YgdGhlIGZhbHNlIHBvc2l0aXZlIHRyYW5zY3JpcHRzLiAgV2hpbGUKSSBhbSBhdCBpdCwgSSB3aWxsIGRyb3AgdGhlIGZlYXR1cmVzIGFubm90YXRlZCBhcyByUk5BLgoKYGBge3IgdGhyZXNob2xkX2N1dG9mZn0KIyMgUGVyZm9ybSBhIGNvdW50L2dlbmUgY3V0b2ZmIGhlcmUKdGhyZXNob2xkIDwtIDQKbWV0aG9kIDwtICJjYmNiIiAgIyMgb3RoZXIgbWV0aG9kcyBpbmNsdWRlICdnZW5lZmlsdGVyJyBhbmQgJ3NpbXBsZScKazEwX2NvdW50IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGsxMF9yYXcsIGZpbHRlcj1tZXRob2QsIHRocmVzaD10aHJlc2hvbGQpKQprOF9jb3VudCA8LSBzbShub3JtYWxpemVfZXhwdChrOF9yYXcsIGZpbHRlcj1tZXRob2QsIHRocmVzaD10aHJlc2hvbGQpKQoKIyMgRmlyc3QgZ2V0IHJpZCBvZiB0aGUgclJOQQpzYl9ycm5hIDwtIHB1dGF0aXZlX2Fubm90YXRpb25zW1sicnJuYV9zdWJ1bml0Il1dICE9ICIiCnJybmFfZHJvcHBlcnMgPC0gcm93bmFtZXMocHV0YXRpdmVfYW5ub3RhdGlvbnMpW3NiX3JybmFdCmsxMF9ub3JybmEgPC0gZXhjbHVkZV9nZW5lc19leHB0KGV4cHQ9azEwX3JhdywgaWRzPXJybmFfZHJvcHBlcnMpCms4X25vcnJuYSA8LSBleGNsdWRlX2dlbmVzX2V4cHQoZXhwdD1rOF9yYXcsIGlkcz1ycm5hX2Ryb3BwZXJzKQpgYGAKCiMjIyBIb3cgbWFueSBoaWdoLWNvdW50IGZlYXR1cmVzIGFyZSBpbiB0aGUgZGF0YT8KCmBgYHtyIGNvdW50X2ZlYXR1cmVzfQpkaW0oZXhwcnMoazEwX2NvdW50KSkKZGltKGV4cHJzKGs4X2NvdW50KSkKYGBgCgojIyBDb25maWRlbmNlIGN1dG9mZgoKTm93IGxldHMgZHJvcCB0aG9zZSBmZWF0dXJlcyBmb3Igd2hpY2ggd2UgaGF2ZSByZWxhdGl2ZWx5IGxvd2VyIGNvbmZpZGVuY2UgaW4KdGhlIEJMQVNUIHJlc3VsdHMgZnJvbSB0cmlub3RhdGUuCgpgYGB7ciBjb25maWRlbmNlX2N1dG9mZn0KIyMgS2VlcCBvbmx5IHRoZSBibGFzdHggaGl0cyB3aXRoIGEgbG93IGUtdmFsdWUgYW5kIGhpZ2ggaWRlbnRpdHkuCmZpbHRlcmVkX2tlZXBlcnMgPC0gcHV0YXRpdmVfYW5ub3RhdGlvbnNbWyJibGFzdHhfZXZhbHVlIl1dIDw9IDFlLTEwICYKICBwdXRhdGl2ZV9hbm5vdGF0aW9uc1tbImJsYXN0eF9pZGVudGl0eSJdXSA+PSA2MAprZWVwZXJzIDwtIHJvd25hbWVzKHB1dGF0aXZlX2Fubm90YXRpb25zKVtmaWx0ZXJlZF9rZWVwZXJzXQojIyBUaGlzIGV4Y2x1ZGVzIGFsbCBidXQgMzMsNDUxIHRyYW5zY3JpcHRzLgoKIyMgTm93IGtlZXAgb25seSB0aG9zZSB0cmFuc2NyaXB0IElEcyB3aGljaCBmYWxsIGludG8gdGhlIGFib3ZlIGNhdGVnb3JpZXMuCmsxMF9jb25mIDwtIGV4Y2x1ZGVfZ2VuZXNfZXhwdChleHB0PWsxMF9ub3JybmEsIGlkcz1rZWVwZXJzLCBtZXRob2Q9ImtlZXAiKQprOF9jb25mIDwtIGV4Y2x1ZGVfZ2VuZXNfZXhwdChleHB0PWs4X25vcnJuYSwgaWRzPWtlZXBlcnMsIG1ldGhvZD0ia2VlcCIpCmBgYAoKIyMgSG93IG1hbnkgaGlnaC1jb25maWRlbmNlIGZlYXR1cmVzIGFyZSBpbiB0aGUgZGF0YT8KCmBgYHtyIGNvbmZfZmVhdHVyZXN9CmRpbShleHBycyhrMTBfY29uZikpCmRpbShleHBycyhrOF9jb25mKSkKYGBgCgojIyBCb3RoIGN1dG9mZnMKCkZpbmFsbHksIGxldHMgYmUgc3VwZXItc3RyaWN0IGFuZCByZW1vdmUgYm90aC4KCmBgYHtyIGJvdGhfY3V0b2ZmfQojIyBQZXJmb3JtIGJvdGggdGhlIGNvbmZpZGVuY2UgYW5kIGNvdW50IGZpbHRyYXRpb24KazEwX2NvbmZfY291bnQgPC0gc20obm9ybWFsaXplX2V4cHQoazEwX2NvbmYsIGZpbHRlcj1tZXRob2QsIHRocmVzaD10aHJlc2hvbGQpKQprOF9jb25mX2NvdW50IDwtIHNtKG5vcm1hbGl6ZV9leHB0KGs4X2NvbmYsIGZpbHRlcj1tZXRob2QsIHRocmVzaD10aHJlc2hvbGQpKQoKcnJuYV9leHB0IDwtIGV4Y2x1ZGVfZ2VuZXNfZXhwdChleHB0PWsxMF9yYXcsIGlkcz1zYl9ycm5hLCBtZXRob2Q9ImtlZXAiKQojIyBUaGlzIGhhcyBvbmx5IDIxIHB1dGF0aXZlIHJSTkEgdHJhbnNjcmlwdHMuCmBgYAoKIyMjIEhvdyBtYW55IGhpZ2gtY291bnQgYW5kIGhpZ2gtY29uZmlkZW5jZSBmZWF0dXJlcz8KCmBgYHtyIGNvbmZfY291bnRfZmVhdHVyZXN9CmRpbShleHBycyhrMTBfY29uZl9jb3VudCkpCmRpbShleHBycyhrOF9jb25mX2NvdW50KSkKYGBgCiMgUGxvdCBjaGFuZ2VzIGluIG51bWJlciBvZiBwdXRhdGl2ZSBnZW5lcwoKVGhlcmUgYXJlIGEgZmV3IHdheXMgdG8gdmlzdWFsaXplIHRoZSBjaGFuZ2VzIHdyb3VnaHQgaW4gdGhlIGRhdGEgYnkgdGhlc2UKb3BlcmF0aW9ucy4gIEhlcmUgYXJlIHR3byBiYXIgcGxvdHMgd2hpY2ggYXR0ZW1wdCB0byBzaG93IHdoYXQgaGFwcGVuZWQsIHRoZQpmaXJzdCBzdGFja3MgdGhlIHJlbGF0aXZlbHktc2l6ZWQgbGlicmFyeSBzaXplcyBhdG9wIG9uZSBhbm90aGVyLCB0aGUgc2Vjb25kCnN0YWNrcyB0aGVtIG9uIHRoZSB4LWF4aXMuCgpgYGB7ciBwdXRhdGl2ZV9nZW5lc30KZ2VuZXNfYnlfc3Vic2V0IDwtIGRhdGEuZnJhbWUoCiAgc2FtcGxlcyA9IGMocmVwKCJ0ZW4iLCA0KSwgcmVwKCJlaWdodCIsIDQpKSwKICBjb2xvcnMgPSBjKHJlcCgiIzFCOUU3NyIsIDQpLCByZXAoIiM3NTcwQjMiLCA0KSksCiAgYWxwaGEgPSBjKCIjMUI5RTc3RkYiLCAiIzFCOUU3N0NDIiwgIiMxQjBFNzdBQSIsCiAgICAgICAgICAgICIjMUIwRTc3NzciLCAiIzc1NzBCM0ZGIiwgIiM3NTcwQjNDQyIsICIjNzU3MEIzQUEiLCAiIzc1NzBCMzc3IiksCiAgdHlwZSA9IHJlcChjKCJyYXciLCAiY291bnQiLCAiY29uZiIsICJjb25mX2NvdW50IiksIDIpLAogIGdlbmVzID0gYyhucm93KGV4cHJzKGsxMF9yYXcpKSwgbnJvdyhleHBycyhrMTBfY291bnQpKSwKICAgICAgICAgICAgbnJvdyhleHBycyhrMTBfY29uZikpLCBucm93KGV4cHJzKGsxMF9jb25mX2NvdW50KSksCiAgICAgICAgICAgIG5yb3coZXhwcnMoazhfcmF3KSksIG5yb3coZXhwcnMoazhfY291bnQpKSwKICAgICAgICAgICAgbnJvdyhleHBycyhrOF9jb25mKSksIG5yb3coZXhwcnMoazhfY29uZl9jb3VudCkpKSkKCmxpYnJhcnkoZ2dwbG90MikKY29sdW1ucyA8LSBnZ3Bsb3QoZ2VuZXNfYnlfc3Vic2V0LCBhZXMoeD1zYW1wbGVzLCB5PWdlbmVzKSkgKwogIGdlb21fY29sKHBvc2l0aW9uPSJpZGVudGl0eSIsIGFlcyhmaWxsPWNvbG9ycywgYWxwaGE9YWxwaGEpLCBjb2xvcj0iYmxhY2siKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzPWMobGV2ZWxzKGFzLmZhY3RvcihnZW5lc19ieV9zdWJzZXQkY29sb3JzKSkpKSArCiAgdGhlbWUoYXhpcy50ZXh0PWdncGxvdDI6OmVsZW1lbnRfdGV4dChzaXplPTEwLCBjb2xvdXI9ImJsYWNrIiksCiAgICAgICAgYXhpcy50ZXh0Lng9Z2dwbG90Mjo6ZWxlbWVudF90ZXh0KGFuZ2xlPTkwLCB2anVzdD0wLjUpLAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmMxIDwtIGdlbmVzX2J5X3N1YnNldFtbInNhbXBsZXMiXV0gPT0gInRlbiIKYzIgPC0gZ2VuZXNfYnlfc3Vic2V0W1sic2FtcGxlcyJdXSA9PSAiZWlnaHQiCnRtcCA8LSBjYmluZChnZW5lc19ieV9zdWJzZXRbYzEsICJnZW5lcyJdLCBnZW5lc19ieV9zdWJzZXRbYzIsICJnZW5lcyJdKQpjb2xuYW1lcyh0bXApIDwtIGMoInRlbiIsICJlaWdodCIpCnJvd25hbWVzKHRtcCkgPC0gYygicmF3IiwgImNvdW50IiwgImNvbmYiLCAiY29uZl9jb3VudCIpCnRtcAoKcHAoZmlsZT0iaW1hZ2VzL2dlbmVzX2J5X2NvbHVtbnMucG5nIiwgaW1hZ2U9Y29sdW1ucykKYGBgCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKICBtZXNzYWdlKHBhc3RlMCgiU2F2aW5nIHRvICIsIHRoaXNfc2F2ZSkpCiAgdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQp9CmBgYAo=