index.html preprocessing.html

1 Annotation version: 20170905

In this document, I will attempt to visualize the relationships among the various samples in this experiment. In the process, I will examine the samples to (hopefully) ensure that they are consistent and that there is not a fatal batch effect or other weakness in the data.

To start, I will print some simple metrics of the entire data set, then split it into more tractable pieces and examine them more thoroughly.

2 Raw global metrics

With the above in mind, here are a couple global plots showing the state of the data.

2.1 mi vs tx

When processing the data, I did 1 alignment of the reads from all samples against a database of miRNAs and then separately against a database of all transcripts. All the samples of library type ‘small’ are really only intended to be compared against the miRNA library while those of type ‘large’ are intended only to search against the transcripts. This is primarily because of the different ways the RNA samples were treated at the beginning of the library preparation. Despite this, I perform both types of alignments for all samples so that I may now look and see that the distributions are different. If everything worked as planned, then the large RNA libraries should have a very different distribution of reads in the miRNA databases and vice-versa. If this is not true, then something might be very wrong.

With that in mind, the following block is going to do some of the graphs and normalize the data. In the following blocks I will print some of the results and consider what they mean.

The following block will serve to generate all the likely subsets of the data.

Lets lay down a couple rules of thumb now:

  1. In all following analyses, do the miRNA first, then transcripts.
  2. All miRNA datasets will start with ‘mmmi’ and transcripts will be ‘mmtx’
## Graph the raw metrics of all samples mapped against the transcripts and miRNAs
##mm_mir <- expt_subset(mm_mir, subset="genotype!='apop'")
##mm_txr <- expt_subset(mm_txr, subset="genotype!='apop'")
mm_mi_metrics <- sm(graph_metrics(mm_mir))
mm_tx_metrics <- sm(graph_metrics(mm_txr))
mmmi_small_metrics <- sm(graph_metrics(mmmi_small))
mmtx_large_metrics <- sm(graph_metrics(mmtx_large))

2.2 A Legend!

First, do not forget to print a legend showing the colors used and what they mean:

mm_mi_metrics$legend$plot

## This should be the same for the mm_mi and mm_tx objects.

2.3 Start with some global metrics

mm_mi_metrics$libsize

The first 8 libraries are small RNA libraries of which the first 4 are exosomes. The important thing to remember is that these are mapped against only the 1978 miRNA features in the mouse Ensembl genome, as such we see that the first 4 are highly enriched in miRNAs, which is excellent.

Therefore, as one would expect, the small exosome RNA libraries have fewer reads than the total cell small RNA libraries, which comprise the set from 5-8. I of course focused immediately upon the last 8 without thinking. These are all the polyA RNA samples, of which the miRNA features are only a small proportion and therefore we see them as <10% the depth of the small RNA samples. I would therefore expect something like the opposite for the transcriptome samples, which are next.

mm_tx_metrics$libsize

Ahh excellent. Once again, the exosome samples have fewer reads than the cells and have many fewer for the small RNA samples than transcript samples, which is good.

3 Sample distributions

From here on, I think I will examine only the small RNA samples and large RNA samples as 2 separate groups.

mmmi_small_metrics$density

mmmi_small_metrics$boxplot

## The sample densities among the small RNA samples look reasonable to me.
mmtx_large_metrics$density

mmtx_large_metrics$boxplot

## This is more problematic from the perspective of the data distributions; but not suprising and
## encouraging from a biological perspective.  The large RNA exosomes have many more genes with 0
## counts.

Considering the heterologous sources of these samples, I think these actually make sense, lets move on and see what else pops up.

3.1 Normalized Metrics

##mmmi_small_norm <- normalize_expt(mmmi_small, transform="log2", norm="quant", convert="cpm", batch="svaseq", filter=TRUE)
mmmi_small_norm <- sm(normalize_expt(mmmi_small, filter=TRUE, norm="quant", convert="cpm", batch="svaseq"))
mmmi_small_norm_metrics <- sm(graph_metrics(mmmi_small_norm))

mmmi_small_norm_metrics$corheat

mmmi_small_norm_metrics$disheat

mmmi_small_norm_metrics$smc

mmmi_small_norm_metrics$pcaplot

mmmi_small_noapop <- subset_expt(mmmi_small, subset="genotype!='apop'")
mmmi_small_noapop_metrics <- sm(graph_metrics(mmmi_small_noapop))

mmmi_small_noapop_metrics$pcaplot

mmmi_small_sva <- sm(normalize_expt(mmmi_small, transform="log2",
                                    norm="quant", convert="raw",
                                    filter=TRUE, batch="fsva"))
plot_pca(mmmi_small_sva)$plot

## The exosome and cell samples split nicely, and the wt/mutants split nicely among them!
## holy asscrackers that is nice!
## newer_data <- normalize_expt(mmmi_small, filter=TRUE, transform="log2", batch="svaseq", norm="quant")
printed_expt <- sm(write_expt(mmmi_small, violin=TRUE,
                              excel=paste0("excel/mmmi_state_withapop-", ver, ".xlsx"),
                              filter=TRUE, transform="log2", norm="quant", convert="raw", batch="fsva"))

It appears that the cellular mRNA samples are a little more problematic; shockingly to me at least, the problematic sample proved to be one of the cellular RNA samples and not an exosome sample! I almost can’t believe that. I think that, given this, I will try an sva/combat adjustment of the data and see what happens, if for nothing else, then to satisfy my curiosity.

tx_colors <- c("#AA0000", "#AA8888", "#0000AA", "#8888AA")
names(tx_colors) <- c("exo_polya_mut", "exo_polya_wt", "cell_polya_mut", "cell_polya_wt")
mmtx_new <- set_expt_colors(mmtx_large, colors=tx_colors)
##mmtx_new <- expt_subset(mmtx_new, subset="sampleid!='HPGL0688'")

mmtx_large_sva <- sm(normalize_expt(mmtx_new, transform="log2",
                                    norm="raw", convert="cpm",
                                    filter=TRUE, batch="fsva"))
plot_pca(mmtx_large_sva)$plot

printed_expt <- sm(write_expt(mmtx_new, excel=paste0("excel/mmtx_state-", ver, ".xlsx"),
                              batch="fsva", norm="raw", convert="cpm", filter=TRUE, violin=TRUE))

## wow, ummm, ok, so it appears that sva sees a significant surrogate variable.
mmtx_new_combat <- sm(normalize_expt(mmtx_new, transform="log2",
                                     norm="quant", convert="cpm",
                                     filter=TRUE, batch="combat_scale"))

plot_pca(mmtx_new_combat)$plot

## But according to this plot, the surrogate varaible is at least not entirely 'batch'
## oh wait, 98.62% of the remaining variance is now on the x-axis!

It appears that there is a significant but not crippling batch effect notable primarily in the large RNA libraries. I suspect that this will be sufficiently ameliorated by just adding batch into the experimental model.

pander::pander(sessionInfo())

R version 3.4.1 (2017-06-30)

**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: parallel, stats, graphics, grDevices, utils, datasets, methods and base

other attached packages: hpgltools(v.2017.01), Biobase(v.2.36.2) and BiocGenerics(v.0.22.0)

loaded via a namespace (and not attached): edgeR(v.3.18.1), bit64(v.0.9-7), splines(v.3.4.1), foreach(v.1.4.3), gtools(v.3.5.0), stats4(v.3.4.1), pander(v.0.6.1), blob(v.1.1.0), yaml(v.2.1.14), ggrepel(v.0.6.5), RSQLite(v.2.0), backports(v.1.1.0), lattice(v.0.20-35), limma(v.3.32.5), quadprog(v.1.5-5), digest(v.0.6.12), RColorBrewer(v.1.1-2), minqa(v.1.2.4), colorspace(v.1.3-2), htmltools(v.0.3.6), preprocessCore(v.1.38.1), Matrix(v.1.2-11), plyr(v.1.8.4), XML(v.3.98-1.9), devtools(v.1.13.3), genefilter(v.1.58.1), xtable(v.1.8-2), corpcor(v.1.6.9), scales(v.0.5.0), gdata(v.2.18.0), openxlsx(v.4.0.17), Rtsne(v.0.13), lme4(v.1.1-13), BiocParallel(v.1.10.1), tibble(v.1.3.4), annotate(v.1.54.0), mgcv(v.1.8-19), IRanges(v.2.10.3), ggplot2(v.2.2.1), withr(v.2.0.0), lazyeval(v.0.2.0), pbkrtest(v.0.4-7), survival(v.2.41-3), magrittr(v.1.5), crayon(v.1.3.2), memoise(v.1.1.0), evaluate(v.0.10.1), MASS(v.7.3-47), gplots(v.3.0.1), doParallel(v.1.0.10), nlme(v.3.1-131), xml2(v.1.1.1), tools(v.3.4.1), directlabels(v.2017.03.31), data.table(v.1.10.4), matrixStats(v.0.52.2), stringr(v.1.2.0), S4Vectors(v.0.14.3), munsell(v.0.4.3), locfit(v.1.5-9.1), AnnotationDbi(v.1.38.2), colorRamps(v.2.3), compiler(v.3.4.1), caTools(v.1.17.1), rlang(v.0.1.2), nloptr(v.1.0.4), grid(v.3.4.1), RCurl(v.1.95-4.8), iterators(v.1.0.8), variancePartition(v.1.6.0), bitops(v.1.0-6), base64enc(v.0.1-3), labeling(v.0.3), rmarkdown(v.1.6), testthat(v.1.0.2), gtable(v.0.2.0), codetools(v.0.2-15), DBI(v.0.7), roxygen2(v.6.0.1), reshape2(v.1.4.2), R6(v.2.2.2), knitr(v.1.17), bit(v.1.1-12), commonmark(v.1.4), rprojroot(v.1.2), KernSmooth(v.2.23-15), stringi(v.1.1.5), sva(v.3.24.4) and Rcpp(v.0.12.12)

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 739e4a10345a89efb17b37e7de07c5811491ccea
## R> packrat::restore()
## This is hpgltools commit: Thu Aug 31 11:24:06 2017 -0400: 739e4a10345a89efb17b37e7de07c5811491ccea
this_save <- paste0(gsub(pattern="\\.Rmd", replace="", x=rmd_file), "-v", ver, ".rda.xz")
message(paste0("Saving to ", this_save))
## Saving to 02_sample_estimation-v20170905.rda.xz
tmp <- sm(saveme(filename=this_save))
LS0tCnRpdGxlOiAiU2FtcGxlIEVzdGltYXRpb24gb2YgTS5tdXNjdWx1cyBzYW1wbGVzLiIKYXV0aG9yOiAiYXRiIGFiZWxld0BnbWFpbC5jb20iCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogaHRtbF9kb2N1bWVudDoKICBjb2RlX2Rvd25sb2FkOiB0cnVlCiAgY29kZV9mb2xkaW5nOiBzaG93CiAgZmlnX2NhcHRpb246IHRydWUKICBmaWdfaGVpZ2h0OiA3CiAgZmlnX3dpZHRoOiA3CiAgaGlnaGxpZ2h0OiB0YW5nbwogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IGNvc21vCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7Cn0KPC9zdHlsZT4KCmBgYHtyIG9wdGlvbnMsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoaHBnbHRvb2xzKQp0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKa25pdHI6Om9wdHNfa25pdCRzZXQocHJvZ3Jlc3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZT1UUlVFLAogICAgICAgICAgICAgICAgICAgICB3aWR0aD05MCwKICAgICAgICAgICAgICAgICAgICAgZWNobz1UUlVFKQprbml0cjo6b3B0c19jaHVuayRzZXQoZXJyb3I9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aD04LAogICAgICAgICAgICAgICAgICAgICAgZmlnLmhlaWdodD04LAogICAgICAgICAgICAgICAgICAgICAgZHBpPTk2KQpvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAga25pdHIuZHVwbGljYXRlLmxhYmVsPSJhbGxvdyIpCmdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQpzZXQuc2VlZCgxKQp2ZXIgPC0gIjIwMTcwOTA1IgpwcmV2aW91c19maWxlIDwtICIwMV9hbm5vdGF0aW9uLlJtZCIKCnRtcCA8LSB0cnkoc20obG9hZG1lKGZpbGVuYW1lPXBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cHJldmlvdXNfZmlsZSksICItdiIsIHZlciwgIi5yZGEueHoiKSkpKQoKcm1kX2ZpbGUgPC0gIjAyX3NhbXBsZV9lc3RpbWF0aW9uLlJtZCIKYGBgCgpgYGB7ciByZW5kZXJpbmcsIGluY2x1ZGU9RkFMU0UsIGV2YWw9RkFMU0V9CnJtYXJrZG93bjo6cmVuZGVyKHJtZF9maWxlKQoKcm1hcmtkb3duOjpyZW5kZXIocm1kX2ZpbGUsIG91dHB1dF9mb3JtYXQ9InBkZl9kb2N1bWVudCIpCmBgYAoKW2luZGV4Lmh0bWxdKGluZGV4Lmh0bWwpIFtwcmVwcm9jZXNzaW5nLmh0bWxdKHByZXByb2Nlc3NpbmcuaHRtbCkKCiMgQW5ub3RhdGlvbiB2ZXJzaW9uOiBgciB2ZXJgCgpJbiB0aGlzIGRvY3VtZW50LCBJIHdpbGwgYXR0ZW1wdCB0byB2aXN1YWxpemUgdGhlIHJlbGF0aW9uc2hpcHMgYW1vbmcgdGhlIHZhcmlvdXMgc2FtcGxlcyBpbiB0aGlzCmV4cGVyaW1lbnQuICBJbiB0aGUgcHJvY2VzcywgSSB3aWxsIGV4YW1pbmUgdGhlIHNhbXBsZXMgdG8gKGhvcGVmdWxseSkgZW5zdXJlIHRoYXQgdGhleSBhcmUKY29uc2lzdGVudCBhbmQgdGhhdCB0aGVyZSBpcyBub3QgYSBmYXRhbCBiYXRjaCBlZmZlY3Qgb3Igb3RoZXIgd2Vha25lc3MgaW4gdGhlIGRhdGEuCgpUbyBzdGFydCwgSSB3aWxsIHByaW50IHNvbWUgc2ltcGxlIG1ldHJpY3Mgb2YgdGhlIGVudGlyZSBkYXRhIHNldCwgdGhlbiBzcGxpdCBpdCBpbnRvIG1vcmUgdHJhY3RhYmxlCnBpZWNlcyBhbmQgZXhhbWluZSB0aGVtIG1vcmUgdGhvcm91Z2hseS4KCiMgUmF3IGdsb2JhbCBtZXRyaWNzCgpXaXRoIHRoZSBhYm92ZSBpbiBtaW5kLCBoZXJlIGFyZSBhIGNvdXBsZSBnbG9iYWwgcGxvdHMgc2hvd2luZyB0aGUgc3RhdGUgb2YgdGhlIGRhdGEuCgojIyBtaSB2cyB0eAoKV2hlbiBwcm9jZXNzaW5nIHRoZSBkYXRhLCBJIGRpZCAxIGFsaWdubWVudCBvZiB0aGUgcmVhZHMgZnJvbSBhbGwgc2FtcGxlcyBhZ2FpbnN0IGEgZGF0YWJhc2Ugb2YKbWlSTkFzIGFuZCB0aGVuIHNlcGFyYXRlbHkgYWdhaW5zdCBhIGRhdGFiYXNlIG9mIGFsbCB0cmFuc2NyaXB0cy4gIEFsbCB0aGUgc2FtcGxlcyBvZiBsaWJyYXJ5IHR5cGUKJ3NtYWxsJyBhcmUgcmVhbGx5IG9ubHkgaW50ZW5kZWQgdG8gYmUgY29tcGFyZWQgYWdhaW5zdCB0aGUgbWlSTkEgbGlicmFyeSB3aGlsZSB0aG9zZSBvZiB0eXBlCidsYXJnZScgYXJlIGludGVuZGVkIG9ubHkgdG8gc2VhcmNoIGFnYWluc3QgdGhlIHRyYW5zY3JpcHRzLiAgVGhpcyBpcyBwcmltYXJpbHkgYmVjYXVzZSBvZiB0aGUKZGlmZmVyZW50IHdheXMgdGhlIFJOQSBzYW1wbGVzIHdlcmUgdHJlYXRlZCBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSBsaWJyYXJ5IHByZXBhcmF0aW9uLiAgRGVzcGl0ZQp0aGlzLCBJIHBlcmZvcm0gYm90aCB0eXBlcyBvZiBhbGlnbm1lbnRzIGZvciBhbGwgc2FtcGxlcyBzbyB0aGF0IEkgbWF5IG5vdyBsb29rIGFuZCBzZWUgdGhhdCB0aGUKZGlzdHJpYnV0aW9ucyBhcmUgZGlmZmVyZW50LiAgSWYgZXZlcnl0aGluZyB3b3JrZWQgYXMgcGxhbm5lZCwgdGhlbiB0aGUgbGFyZ2UgUk5BIGxpYnJhcmllcyBzaG91bGQKaGF2ZSBhIHZlcnkgZGlmZmVyZW50IGRpc3RyaWJ1dGlvbiBvZiByZWFkcyBpbiB0aGUgbWlSTkEgZGF0YWJhc2VzIGFuZCB2aWNlLXZlcnNhLiAgSWYgdGhpcyBpcyBub3QKdHJ1ZSwgdGhlbiBzb21ldGhpbmcgbWlnaHQgYmUgdmVyeSB3cm9uZy4KCldpdGggdGhhdCBpbiBtaW5kLCB0aGUgZm9sbG93aW5nIGJsb2NrIGlzIGdvaW5nIHRvIGRvIHNvbWUgb2YgdGhlIGdyYXBocyBhbmQgbm9ybWFsaXplIHRoZSBkYXRhLiAgSW4KdGhlIGZvbGxvd2luZyBibG9ja3MgSSB3aWxsIHByaW50IHNvbWUgb2YgdGhlIHJlc3VsdHMgYW5kIGNvbnNpZGVyIHdoYXQgdGhleSBtZWFuLgoKVGhlIGZvbGxvd2luZyBibG9jayB3aWxsIHNlcnZlIHRvIGdlbmVyYXRlIGFsbCB0aGUgbGlrZWx5IHN1YnNldHMgb2YgdGhlIGRhdGEuCgpMZXRzIGxheSBkb3duIGEgY291cGxlIHJ1bGVzIG9mIHRodW1iIG5vdzoKCjEuICBJbiBhbGwgZm9sbG93aW5nIGFuYWx5c2VzLCBkbyB0aGUgbWlSTkEgZmlyc3QsIHRoZW4gdHJhbnNjcmlwdHMuCjIuICBBbGwgbWlSTkEgZGF0YXNldHMgd2lsbCBzdGFydCB3aXRoICdtbW1pJyBhbmQgdHJhbnNjcmlwdHMgd2lsbCBiZSAnbW10eCcKCmBgYHtyIGJhc2VfbWV0cmljcywgZmlnLnNob3c9ImhpZGUifQojIyBHcmFwaCB0aGUgcmF3IG1ldHJpY3Mgb2YgYWxsIHNhbXBsZXMgbWFwcGVkIGFnYWluc3QgdGhlIHRyYW5zY3JpcHRzIGFuZCBtaVJOQXMKIyNtbV9taXIgPC0gZXhwdF9zdWJzZXQobW1fbWlyLCBzdWJzZXQ9Imdlbm90eXBlIT0nYXBvcCciKQojI21tX3R4ciA8LSBleHB0X3N1YnNldChtbV90eHIsIHN1YnNldD0iZ2Vub3R5cGUhPSdhcG9wJyIpCm1tX21pX21ldHJpY3MgPC0gc20oZ3JhcGhfbWV0cmljcyhtbV9taXIpKQptbV90eF9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3MobW1fdHhyKSkKbW1taV9zbWFsbF9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3MobW1taV9zbWFsbCkpCm1tdHhfbGFyZ2VfbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKG1tdHhfbGFyZ2UpKQpgYGAKCiMjIEEgTGVnZW5kIQoKRmlyc3QsIGRvIG5vdCBmb3JnZXQgdG8gcHJpbnQgYSBsZWdlbmQgc2hvd2luZyB0aGUgY29sb3JzIHVzZWQgYW5kIHdoYXQgdGhleSBtZWFuOgoKYGBge3IgbGVnZW5kfQptbV9taV9tZXRyaWNzJGxlZ2VuZCRwbG90CiMjIFRoaXMgc2hvdWxkIGJlIHRoZSBzYW1lIGZvciB0aGUgbW1fbWkgYW5kIG1tX3R4IG9iamVjdHMuCmBgYAoKIyMgU3RhcnQgd2l0aCBzb21lIGdsb2JhbCBtZXRyaWNzCgpgYGB7ciBsaWJzaXplX21pfQptbV9taV9tZXRyaWNzJGxpYnNpemUKYGBgCgpUaGUgZmlyc3QgOCBsaWJyYXJpZXMgYXJlIHNtYWxsIFJOQSBsaWJyYXJpZXMgb2Ygd2hpY2ggdGhlIGZpcnN0IDQgYXJlIGV4b3NvbWVzLgpUaGUgaW1wb3J0YW50IHRoaW5nIHRvIHJlbWVtYmVyIGlzIHRoYXQgdGhlc2UgYXJlIG1hcHBlZCBhZ2FpbnN0IG9ubHkgdGhlIDE5NzggbWlSTkEgZmVhdHVyZXMgaW4KdGhlIG1vdXNlIEVuc2VtYmwgZ2Vub21lLCBhcyBzdWNoIHdlIHNlZSB0aGF0IHRoZSBmaXJzdCA0IGFyZSBoaWdobHkgZW5yaWNoZWQgaW4gbWlSTkFzLCB3aGljaCBpcwpleGNlbGxlbnQuCgpUaGVyZWZvcmUsIGFzIG9uZSB3b3VsZCBleHBlY3QsIHRoZSBzbWFsbCBleG9zb21lIFJOQSBsaWJyYXJpZXMgaGF2ZSBmZXdlciByZWFkcyB0aGFuIHRoZSB0b3RhbApjZWxsIHNtYWxsIFJOQSBsaWJyYXJpZXMsIHdoaWNoIGNvbXByaXNlIHRoZSBzZXQgZnJvbSA1LTguCkkgb2YgY291cnNlIGZvY3VzZWQgaW1tZWRpYXRlbHkgdXBvbiB0aGUgbGFzdCA4IHdpdGhvdXQgdGhpbmtpbmcuICBUaGVzZSBhcmUgYWxsIHRoZSBwb2x5QSBSTkEKc2FtcGxlcywgb2Ygd2hpY2ggdGhlIG1pUk5BIGZlYXR1cmVzIGFyZSBvbmx5IGEgc21hbGwgcHJvcG9ydGlvbiBhbmQgdGhlcmVmb3JlIHdlIHNlZSB0aGVtIGFzCjwxMCUgdGhlIGRlcHRoIG9mIHRoZSBzbWFsbCBSTkEgc2FtcGxlcy4KSSB3b3VsZCB0aGVyZWZvcmUgZXhwZWN0IHNvbWV0aGluZyBsaWtlIHRoZSBvcHBvc2l0ZSBmb3IgdGhlIHRyYW5zY3JpcHRvbWUgc2FtcGxlcywgd2hpY2ggYXJlIG5leHQuCgpgYGB7ciBsaWJzaXplX3R4fQptbV90eF9tZXRyaWNzJGxpYnNpemUKYGBgCgpBaGggZXhjZWxsZW50LiAgT25jZSBhZ2FpbiwgdGhlIGV4b3NvbWUgc2FtcGxlcyBoYXZlIGZld2VyIHJlYWRzIHRoYW4gdGhlIGNlbGxzIGFuZCBoYXZlIG1hbnkKZmV3ZXIgZm9yIHRoZSBzbWFsbCBSTkEgc2FtcGxlcyB0aGFuIHRyYW5zY3JpcHQgc2FtcGxlcywgd2hpY2ggaXMgZ29vZC4KCiMgU2FtcGxlIGRpc3RyaWJ1dGlvbnMKCkZyb20gaGVyZSBvbiwgSSB0aGluayBJIHdpbGwgZXhhbWluZSBvbmx5IHRoZSBzbWFsbCBSTkEgc2FtcGxlcyBhbmQgbGFyZ2UgUk5BIHNhbXBsZXMgYXMgMiBzZXBhcmF0ZQpncm91cHMuCgpgYGB7ciBkZW5zaXRpZXN9Cm1tbWlfc21hbGxfbWV0cmljcyRkZW5zaXR5Cm1tbWlfc21hbGxfbWV0cmljcyRib3hwbG90CiMjIFRoZSBzYW1wbGUgZGVuc2l0aWVzIGFtb25nIHRoZSBzbWFsbCBSTkEgc2FtcGxlcyBsb29rIHJlYXNvbmFibGUgdG8gbWUuCm1tdHhfbGFyZ2VfbWV0cmljcyRkZW5zaXR5Cm1tdHhfbGFyZ2VfbWV0cmljcyRib3hwbG90CiMjIFRoaXMgaXMgbW9yZSBwcm9ibGVtYXRpYyBmcm9tIHRoZSBwZXJzcGVjdGl2ZSBvZiB0aGUgZGF0YSBkaXN0cmlidXRpb25zOyBidXQgbm90IHN1cHJpc2luZyBhbmQKIyMgZW5jb3VyYWdpbmcgZnJvbSBhIGJpb2xvZ2ljYWwgcGVyc3BlY3RpdmUuICBUaGUgbGFyZ2UgUk5BIGV4b3NvbWVzIGhhdmUgbWFueSBtb3JlIGdlbmVzIHdpdGggMAojIyBjb3VudHMuCmBgYAoKQ29uc2lkZXJpbmcgdGhlIGhldGVyb2xvZ291cyBzb3VyY2VzIG9mIHRoZXNlIHNhbXBsZXMsIEkgdGhpbmsgdGhlc2UgYWN0dWFsbHkgbWFrZSBzZW5zZSwgbGV0cyBtb3ZlCm9uIGFuZCBzZWUgd2hhdCBlbHNlIHBvcHMgdXAuCgoKIyMgTm9ybWFsaXplZCBNZXRyaWNzCgpgYGB7ciB2aWV3X25vcm1fbWV0cmljc30KIyNtbW1pX3NtYWxsX25vcm0gPC0gbm9ybWFsaXplX2V4cHQobW1taV9zbWFsbCwgdHJhbnNmb3JtPSJsb2cyIiwgbm9ybT0icXVhbnQiLCBjb252ZXJ0PSJjcG0iLCBiYXRjaD0ic3Zhc2VxIiwgZmlsdGVyPVRSVUUpCm1tbWlfc21hbGxfbm9ybSA8LSBzbShub3JtYWxpemVfZXhwdChtbW1pX3NtYWxsLCBmaWx0ZXI9VFJVRSwgbm9ybT0icXVhbnQiLCBjb252ZXJ0PSJjcG0iLCBiYXRjaD0ic3Zhc2VxIikpCm1tbWlfc21hbGxfbm9ybV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3MobW1taV9zbWFsbF9ub3JtKSkKbW1taV9zbWFsbF9ub3JtX21ldHJpY3MkY29yaGVhdAptbW1pX3NtYWxsX25vcm1fbWV0cmljcyRkaXNoZWF0Cm1tbWlfc21hbGxfbm9ybV9tZXRyaWNzJHNtYwptbW1pX3NtYWxsX25vcm1fbWV0cmljcyRwY2FwbG90CgptbW1pX3NtYWxsX25vYXBvcCA8LSBzdWJzZXRfZXhwdChtbW1pX3NtYWxsLCBzdWJzZXQ9Imdlbm90eXBlIT0nYXBvcCciKQptbW1pX3NtYWxsX25vYXBvcF9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3MobW1taV9zbWFsbF9ub2Fwb3ApKQptbW1pX3NtYWxsX25vYXBvcF9tZXRyaWNzJHBjYXBsb3QKCm1tbWlfc21hbGxfc3ZhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1tbWlfc21hbGwsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm09InF1YW50IiwgY29udmVydD0icmF3IiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyPVRSVUUsIGJhdGNoPSJmc3ZhIikpCnBsb3RfcGNhKG1tbWlfc21hbGxfc3ZhKSRwbG90CiMjIFRoZSBleG9zb21lIGFuZCBjZWxsIHNhbXBsZXMgc3BsaXQgbmljZWx5LCBhbmQgdGhlIHd0L211dGFudHMgc3BsaXQgbmljZWx5IGFtb25nIHRoZW0hCiMjIGhvbHkgYXNzY3JhY2tlcnMgdGhhdCBpcyBuaWNlIQojIyBuZXdlcl9kYXRhIDwtIG5vcm1hbGl6ZV9leHB0KG1tbWlfc21hbGwsIGZpbHRlcj1UUlVFLCB0cmFuc2Zvcm09ImxvZzIiLCBiYXRjaD0ic3Zhc2VxIiwgbm9ybT0icXVhbnQiKQpwcmludGVkX2V4cHQgPC0gc20od3JpdGVfZXhwdChtbW1pX3NtYWxsLCB2aW9saW49VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhjZWw9cGFzdGUwKCJleGNlbC9tbW1pX3N0YXRlX3dpdGhhcG9wLSIsIHZlciwgIi54bHN4IiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcj1UUlVFLCB0cmFuc2Zvcm09ImxvZzIiLCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9InJhdyIsIGJhdGNoPSJmc3ZhIikpCmBgYAoKSXQgYXBwZWFycyB0aGF0IHRoZSBjZWxsdWxhciBtUk5BIHNhbXBsZXMgYXJlIGEgbGl0dGxlIG1vcmUgcHJvYmxlbWF0aWM7IHNob2NraW5nbHkgdG8gbWUgYXQgbGVhc3QsCnRoZSBwcm9ibGVtYXRpYyBzYW1wbGUgcHJvdmVkIHRvIGJlIG9uZSBvZiB0aGUgY2VsbHVsYXIgUk5BIHNhbXBsZXMgYW5kIG5vdCBhbiBleG9zb21lIHNhbXBsZSEgIEkKYWxtb3N0IGNhbid0IGJlbGlldmUgdGhhdC4gIEkgdGhpbmsgdGhhdCwgZ2l2ZW4gdGhpcywgSSB3aWxsIHRyeSBhbiBzdmEvY29tYmF0IGFkanVzdG1lbnQgb2YgdGhlIGRhdGEgYW5kCnNlZSB3aGF0IGhhcHBlbnMsIGlmIGZvciBub3RoaW5nIGVsc2UsIHRoZW4gdG8gc2F0aXNmeSBteSBjdXJpb3NpdHkuCgpgYGB7ciBzdmFfcm5hfQp0eF9jb2xvcnMgPC0gYygiI0FBMDAwMCIsICIjQUE4ODg4IiwgIiMwMDAwQUEiLCAiIzg4ODhBQSIpCm5hbWVzKHR4X2NvbG9ycykgPC0gYygiZXhvX3BvbHlhX211dCIsICJleG9fcG9seWFfd3QiLCAiY2VsbF9wb2x5YV9tdXQiLCAiY2VsbF9wb2x5YV93dCIpCm1tdHhfbmV3IDwtIHNldF9leHB0X2NvbG9ycyhtbXR4X2xhcmdlLCBjb2xvcnM9dHhfY29sb3JzKQojI21tdHhfbmV3IDwtIGV4cHRfc3Vic2V0KG1tdHhfbmV3LCBzdWJzZXQ9InNhbXBsZWlkIT0nSFBHTDA2ODgnIikKCm1tdHhfbGFyZ2Vfc3ZhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KG1tdHhfbmV3LCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtPSJyYXciLCBjb252ZXJ0PSJjcG0iLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXI9VFJVRSwgYmF0Y2g9ImZzdmEiKSkKcGxvdF9wY2EobW10eF9sYXJnZV9zdmEpJHBsb3QKCnByaW50ZWRfZXhwdCA8LSBzbSh3cml0ZV9leHB0KG1tdHhfbmV3LCBleGNlbD1wYXN0ZTAoImV4Y2VsL21tdHhfc3RhdGUtIiwgdmVyLCAiLnhsc3giKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmF0Y2g9ImZzdmEiLCBub3JtPSJyYXciLCBjb252ZXJ0PSJjcG0iLCBmaWx0ZXI9VFJVRSwgdmlvbGluPVRSVUUpKQojIyB3b3csIHVtbW0sIG9rLCBzbyBpdCBhcHBlYXJzIHRoYXQgc3ZhIHNlZXMgYSBzaWduaWZpY2FudCBzdXJyb2dhdGUgdmFyaWFibGUuCm1tdHhfbmV3X2NvbWJhdCA8LSBzbShub3JtYWxpemVfZXhwdChtbXR4X25ldywgdHJhbnNmb3JtPSJsb2cyIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vcm09InF1YW50IiwgY29udmVydD0iY3BtIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpbHRlcj1UUlVFLCBiYXRjaD0iY29tYmF0X3NjYWxlIikpCnBsb3RfcGNhKG1tdHhfbmV3X2NvbWJhdCkkcGxvdAojIyBCdXQgYWNjb3JkaW5nIHRvIHRoaXMgcGxvdCwgdGhlIHN1cnJvZ2F0ZSB2YXJhaWJsZSBpcyBhdCBsZWFzdCBub3QgZW50aXJlbHkgJ2JhdGNoJwojIyBvaCB3YWl0LCA5OC42MiUgb2YgdGhlIHJlbWFpbmluZyB2YXJpYW5jZSBpcyBub3cgb24gdGhlIHgtYXhpcyEKYGBgCgpJdCBhcHBlYXJzIHRoYXQgdGhlcmUgaXMgYSBzaWduaWZpY2FudCBidXQgbm90IGNyaXBwbGluZyBiYXRjaCBlZmZlY3Qgbm90YWJsZSBwcmltYXJpbHkgaW4gdGhlIGxhcmdlClJOQSBsaWJyYXJpZXMuICBJIHN1c3BlY3QgdGhhdCB0aGlzIHdpbGwgYmUgc3VmZmljaWVudGx5IGFtZWxpb3JhdGVkIGJ5IGp1c3QgYWRkaW5nIGJhdGNoIGludG8gdGhlCmV4cGVyaW1lbnRhbCBtb2RlbC4KCmBgYHtyIHNhdmVtZX0KcGFuZGVyOjpwYW5kZXIoc2Vzc2lvbkluZm8oKSkKbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCnRoaXNfc2F2ZSA8LSBwYXN0ZTAoZ3N1YihwYXR0ZXJuPSJcXC5SbWQiLCByZXBsYWNlPSIiLCB4PXJtZF9maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpCm1lc3NhZ2UocGFzdGUwKCJTYXZpbmcgdG8gIiwgdGhpc19zYXZlKSkKdG1wIDwtIHNtKHNhdmVtZShmaWxlbmFtZT10aGlzX3NhdmUpKQpgYGAK