1 Sample Estimation version: 20180212

This document should make clear the suitability of our yeast data for differential expression analyses. It should also give some ideas about the depth and distribution of the data.

1.1 Visualizing raw data

There are lots of toys we have learned to use to play with with raw data and explore stuff like batch effects or non-canonical distributions or skewed counts. hpgltools provides some functionality to make this process easier. The graphs shown below and many more are generated with the wrapper ‘graph_metrics()’ but that takes away the chance to explain the graphs as I generate them.

sc_filt <- sm(normalize_expt(sc2_expt, filter=TRUE))
sc2_libsize <- plot_libsize(sc2_expt)
pp(file="images/sc2_libsize.png", image=sc2_libsize$plot)
## Wrote the image to: images/sc2_libsize.png

## The range is from 22-36 million reads, that seems quite reasonable to me.

sc2_nonzero <- plot_nonzero(sc_filt)
pp(file="images/sc2_nonzero.png", image=sc2_nonzero$plot)
## Wrote the image to: images/sc2_nonzero.png

## Wow, these samples are super-well represented.  The 'worst' samples have only 3 more genes with
## ~0 reads than the 'best'.  That is amazing.

sc2_density <- sm(plot_density(sc_filt))
pp(file="images/sc2_density.png", image=sc2_density$plot)
## Wrote the image to: images/sc2_density.png

## These look quite good for non-normalized data.

sc2_boxplot <- sm(plot_boxplot(sc_filt))
pp(file="images/sc2_boxplot.png", image=sc2_boxplot)
## Wrote the image to: images/sc2_boxplot.png

## This is the same as the density plot, looks good to me.

2 Normalize and visualize

Here we will apply the ‘default’ normalization preferred by Najib and then re-graph the data to look at the distributions again.

sc_norm <- sm(normalize_expt(sc2_expt, transform="log2", norm="quant", convert="cpm", filter=TRUE))
sc_metrics <- sm(graph_metrics(sc_norm))

The data should now be normalized, lets view some metrics post-facto.

pp(file="illustrator_input/legend.pdf", image=sc_metrics$legend)
## Wrote the image to: illustrator_input/legend.pdf

pp(file="illustrator_input/norm_corheat.pdf", image=sc_metrics$corheat)
## Wrote the image to: illustrator_input/norm_corheat.pdf

pp(file="illustrator_input/norm_disheat.pdf", image=sc_metrics$disheat)
## Wrote the image to: illustrator_input/norm_disheat.pdf

## There is definitely something odd going on here.
## It looks like many of the samples are clustering in pairs where one group of pairs
## consists of the first 8 samples and the second group consists of the second 8 samples.
## This is analagous to some observations we made in IGV and somewhat worrisome.

pp(file="illustrator_input/norm_smc.pdf", image=sc_metrics$smc)
## Wrote the image to: illustrator_input/norm_smc.pdf

## The samples are very well behaved, none fall below the red line.

pp(file="illustrator_input/norm_pca.pdf", image=sc_metrics$pcaplot)
## Wrote the image to: illustrator_input/norm_pca.pdf

## This shows us that peculiar split in another way.  That is really strange.

pp(file="illustrator_input/norm_tsne.pdf", image=sc_metrics$tsneplot)
## Wrote the image to: illustrator_input/norm_tsne.pdf

3 Try a batch estimation

In the following stanza I will apply a few batch/surrogate estimates in an attempt to get a handle on what is going on with these strange data splits.

In each case I will plot a quick pca to get some idea of what happened.

For these estimates, I will leave off cpm/quantile normalizations to try to isolate the effects of only the surrogate estimates on the data.

3.1 sva defaults

Start with the default unsupervised sva estimate.

sc2_sva <- sm(normalize_expt(sc2_expt, transform="log2",
                             filter=TRUE, batch="sva", low_to_zero=TRUE))
sc2_sva_metrics <- sm(graph_metrics(sc2_sva))
pp(file="images/sc2_sva_pca.png", image=sc2_sva_metrics$pcaplot)
## Wrote the image to: images/sc2_sva_pca.png

## hmm better I suppose, but hpgl0774 is 100% kooky.

pp(file="images/sc2_sva_tsne.png", image=sc2_sva_metrics$tsneplot)
## Wrote the image to: images/sc2_sva_tsne.png

3.2 fsva

This is a modification of the sva defaults, here is a quote from the documentation:

“This function performs frozen surrogate variable analysis as described in Parker, Corrada Bravo and Leek 2013. The approach uses a training database to create surrogate variables which are then used to remove batch effects both from the training database and a new data set for prediction purposes.”

sc2_fsva <- sm(normalize_expt(sc2_expt, transform="log2",
                              filter=TRUE, batch="fsva"))
sc2_fsva_metrics <- sm(graph_metrics(sc2_fsva))

fsva seems like it might be useful, but also potentially a too-large modification of the data.

pp(file="sc2_fsva_pca.png", image=sc2_fsva_metrics$pcaplot)
## Wrote the image to: sc2_fsva_pca.png

pp(file="sc2_fsvs_tsne.png", image=sc2_fsva_metrics$tsneplot)
## Wrote the image to: sc2_fsvs_tsne.png

4 Variance hunting

I want to apply a few tools to try to get a handle on where this strange variance is coming from.

varhunt <- pca_information(expt_data=sc2_expt,
                           expt_factors=c("condition","batch","originalbatch", "incubationtime"))
varhunt$anova_fstat_heatmap
## Both batch estimates are very strong on PC1 and PC2, incubation time comes out on the 3rd PC.
## The condition looks like it is stuck with with, unfortunately.

sc2_varpart <- varpart(expt=sc2_expt, predictor=NULL,
                       factors=c("condition","batch","originalbatch", "incubationtime"))
sc2_varpart$partition_plot
## Well here at least, it looks like batch kicks ass.

5 Write the expt

Let us apply the same set of normalizations/surrogate estimates and write out the resulting tables.

fun <- write_expt(sc2_expt, excel=paste0("excel/samples_written-v", ver, ".xlsx"),
                  filter=TRUE, norm="raw", batch="fsva", transform="log2", violin=TRUE)
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")
  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 5d8c266e48bb9f73cdac8300e5c7c9f5baf003dc
## R> packrat::restore()
## This is hpgltools commit: Wed Mar 21 15:55:32 2018 -0400: 5d8c266e48bb9f73cdac8300e5c7c9f5baf003dc
LS0tCnRpdGxlOiAiUy4gY2VyZXZpc2lhZSAyMDE3OiBzYW1wbGUgZXN0aW1hdGlvbi4iCmF1dGhvcjogImF0YiBhYmVsZXdAZ21haWwuY29tIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKIGh0bWxfZG9jdW1lbnQ6CiAgY29kZV9kb3dubG9hZDogdHJ1ZQogIGNvZGVfZm9sZGluZzogc2hvdwogIGZpZ19jYXB0aW9uOiB0cnVlCiAgZmlnX2hlaWdodDogNwogIGZpZ193aWR0aDogNwogIGhpZ2hsaWdodDogZGVmYXVsdAogIGtlZXBfbWQ6IGZhbHNlCiAgbW9kZTogc2VsZmNvbnRhaW5lZAogIG51bWJlcl9zZWN0aW9uczogdHJ1ZQogIHNlbGZfY29udGFpbmVkOiB0cnVlCiAgdGhlbWU6IHJlYWRhYmxlCiAgdG9jOiB0cnVlCiAgdG9jX2Zsb2F0OgogICAgY29sbGFwc2VkOiBmYWxzZQogICAgc21vb3RoX3Njcm9sbDogZmFsc2UKLS0tCgo8c3R5bGU+CiAgYm9keSAubWFpbi1jb250YWluZXIgewogICAgbWF4LXdpZHRoOiAxNjAwcHg7CiAgfQo8L3N0eWxlPgoKYGBge3Igb3B0aW9ucywgaW5jbHVkZT1GQUxTRX0KaWYgKCFpc1RSVUUoZ2V0MCgic2tpcF9sb2FkIikpKSB7CiAgbGlicmFyeSgiaHBnbHRvb2xzIikKICB0dCA8LSBkZXZ0b29sczo6bG9hZF9hbGwoIn4vaHBnbHRvb2xzIikKICBrbml0cjo6b3B0c19rbml0JHNldChwcm9ncmVzcz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2U9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICB3aWR0aD05MCwKICAgICAgICAgICAgICAgICAgICAgICBlY2hvPVRSVUUpCiAga25pdHI6Om9wdHNfY2h1bmskc2V0KGVycm9yPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgIGZpZy53aWR0aD04LAogICAgICAgICAgICAgICAgICAgICAgICBmaWcuaGVpZ2h0PTgsCiAgICAgICAgICAgICAgICAgICAgICAgIGRwaT05NikKICBvbGRfb3B0aW9ucyA8LSBvcHRpb25zKGRpZ2l0cz00LAogICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgIGtuaXRyLmR1cGxpY2F0ZS5sYWJlbD0iYWxsb3ciKQogIGdncGxvdDI6OnRoZW1lX3NldChnZ3Bsb3QyOjp0aGVtZV9idyhiYXNlX3NpemU9MTApKQogIHNldC5zZWVkKDEpCiAgdmVyIDwtICIyMDE4MDIxMiIKICBwcmV2aW91c19maWxlIDwtICIwMV9hbm5vdGF0aW9uLlJtZCIKCiAgdG1wIDwtIHRyeShzbShsb2FkbWUoZmlsZW5hbWU9cGFzdGUwKGdzdWIocGF0dGVybj0iXFwuUm1kIiwgcmVwbGFjZT0iIiwgeD1wcmV2aW91c19maWxlKSwgIi12IiwgdmVyLCAiLnJkYS54eiIpKSkpCiAgcm1kX2ZpbGUgPC0gIjAyX3NhbXBsZV9lc3RpbWF0aW9uLlJtZCIKfQpgYGAKCiMgU2FtcGxlIEVzdGltYXRpb24gdmVyc2lvbjogYHIgdmVyYAoKVGhpcyBkb2N1bWVudCBzaG91bGQgbWFrZSBjbGVhciB0aGUgc3VpdGFiaWxpdHkgb2Ygb3VyIHllYXN0IGRhdGEgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uCmFuYWx5c2VzLiAgSXQgc2hvdWxkIGFsc28gZ2l2ZSBzb21lIGlkZWFzIGFib3V0IHRoZSBkZXB0aCBhbmQgZGlzdHJpYnV0aW9uIG9mCnRoZSBkYXRhLgoKIyMgVmlzdWFsaXppbmcgcmF3IGRhdGEKClRoZXJlIGFyZSBsb3RzIG9mIHRveXMgd2UgaGF2ZSBsZWFybmVkIHRvIHVzZSB0byBwbGF5IHdpdGggd2l0aCByYXcgZGF0YSBhbmQgZXhwbG9yZSBzdHVmZiBsaWtlCmJhdGNoIGVmZmVjdHMgb3Igbm9uLWNhbm9uaWNhbCBkaXN0cmlidXRpb25zIG9yIHNrZXdlZCBjb3VudHMuICBocGdsdG9vbHMgcHJvdmlkZXMgc29tZSBmdW5jdGlvbmFsaXR5CnRvIG1ha2UgdGhpcyBwcm9jZXNzIGVhc2llci4gIFRoZSBncmFwaHMgc2hvd24gYmVsb3cgYW5kIG1hbnkgbW9yZSBhcmUgZ2VuZXJhdGVkIHdpdGggdGhlIHdyYXBwZXIKJ2dyYXBoX21ldHJpY3MoKScgYnV0IHRoYXQgdGFrZXMgYXdheSB0aGUgY2hhbmNlIHRvIGV4cGxhaW4gdGhlIGdyYXBocyBhcyBJIGdlbmVyYXRlIHRoZW0uCgpgYGB7ciByYXdfZXhwbG9yZX0Kc2NfZmlsdCA8LSBzbShub3JtYWxpemVfZXhwdChzYzJfZXhwdCwgZmlsdGVyPVRSVUUpKQpzYzJfbGlic2l6ZSA8LSBwbG90X2xpYnNpemUoc2MyX2V4cHQpCnBwKGZpbGU9ImltYWdlcy9zYzJfbGlic2l6ZS5wbmciLCBpbWFnZT1zYzJfbGlic2l6ZSRwbG90KQojIyBUaGUgcmFuZ2UgaXMgZnJvbSAyMi0zNiBtaWxsaW9uIHJlYWRzLCB0aGF0IHNlZW1zIHF1aXRlIHJlYXNvbmFibGUgdG8gbWUuCgpzYzJfbm9uemVybyA8LSBwbG90X25vbnplcm8oc2NfZmlsdCkKcHAoZmlsZT0iaW1hZ2VzL3NjMl9ub256ZXJvLnBuZyIsIGltYWdlPXNjMl9ub256ZXJvJHBsb3QpCiMjIFdvdywgdGhlc2Ugc2FtcGxlcyBhcmUgc3VwZXItd2VsbCByZXByZXNlbnRlZC4gIFRoZSAnd29yc3QnIHNhbXBsZXMgaGF2ZSBvbmx5IDMgbW9yZSBnZW5lcyB3aXRoCiMjIH4wIHJlYWRzIHRoYW4gdGhlICdiZXN0Jy4gIFRoYXQgaXMgYW1hemluZy4KCnNjMl9kZW5zaXR5IDwtIHNtKHBsb3RfZGVuc2l0eShzY19maWx0KSkKcHAoZmlsZT0iaW1hZ2VzL3NjMl9kZW5zaXR5LnBuZyIsIGltYWdlPXNjMl9kZW5zaXR5JHBsb3QpCiMjIFRoZXNlIGxvb2sgcXVpdGUgZ29vZCBmb3Igbm9uLW5vcm1hbGl6ZWQgZGF0YS4KCnNjMl9ib3hwbG90IDwtIHNtKHBsb3RfYm94cGxvdChzY19maWx0KSkKcHAoZmlsZT0iaW1hZ2VzL3NjMl9ib3hwbG90LnBuZyIsIGltYWdlPXNjMl9ib3hwbG90KQojIyBUaGlzIGlzIHRoZSBzYW1lIGFzIHRoZSBkZW5zaXR5IHBsb3QsIGxvb2tzIGdvb2QgdG8gbWUuCmBgYAoKIyBOb3JtYWxpemUgYW5kIHZpc3VhbGl6ZQoKSGVyZSB3ZSB3aWxsIGFwcGx5IHRoZSAnZGVmYXVsdCcgbm9ybWFsaXphdGlvbiBwcmVmZXJyZWQgYnkgTmFqaWIgYW5kIHRoZW4KcmUtZ3JhcGggdGhlIGRhdGEgdG8gbG9vayBhdCB0aGUgZGlzdHJpYnV0aW9ucyBhZ2Fpbi4KCmBgYHtyIG5vcm1hbGl6ZSwgZmlnLnNob3c9ImhpZGUifQpzY19ub3JtIDwtIHNtKG5vcm1hbGl6ZV9leHB0KHNjMl9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLCBub3JtPSJxdWFudCIsIGNvbnZlcnQ9ImNwbSIsIGZpbHRlcj1UUlVFKSkKc2NfbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHNjX25vcm0pKQpgYGAKClRoZSBkYXRhIHNob3VsZCBub3cgYmUgbm9ybWFsaXplZCwgbGV0cyB2aWV3IHNvbWUgbWV0cmljcyBwb3N0LWZhY3RvLgoKYGBge3Igbm9ybXZpen0KcHAoZmlsZT0iaWxsdXN0cmF0b3JfaW5wdXQvbGVnZW5kLnBkZiIsIGltYWdlPXNjX21ldHJpY3MkbGVnZW5kKQpwcChmaWxlPSJpbGx1c3RyYXRvcl9pbnB1dC9ub3JtX2NvcmhlYXQucGRmIiwgaW1hZ2U9c2NfbWV0cmljcyRjb3JoZWF0KQpwcChmaWxlPSJpbGx1c3RyYXRvcl9pbnB1dC9ub3JtX2Rpc2hlYXQucGRmIiwgaW1hZ2U9c2NfbWV0cmljcyRkaXNoZWF0KQojIyBUaGVyZSBpcyBkZWZpbml0ZWx5IHNvbWV0aGluZyBvZGQgZ29pbmcgb24gaGVyZS4KIyMgSXQgbG9va3MgbGlrZSBtYW55IG9mIHRoZSBzYW1wbGVzIGFyZSBjbHVzdGVyaW5nIGluIHBhaXJzIHdoZXJlIG9uZSBncm91cCBvZiBwYWlycwojIyBjb25zaXN0cyBvZiB0aGUgZmlyc3QgOCBzYW1wbGVzIGFuZCB0aGUgc2Vjb25kIGdyb3VwIGNvbnNpc3RzIG9mIHRoZSBzZWNvbmQgOCBzYW1wbGVzLgojIyBUaGlzIGlzIGFuYWxhZ291cyB0byBzb21lIG9ic2VydmF0aW9ucyB3ZSBtYWRlIGluIElHViBhbmQgc29tZXdoYXQgd29ycmlzb21lLgoKcHAoZmlsZT0iaWxsdXN0cmF0b3JfaW5wdXQvbm9ybV9zbWMucGRmIiwgaW1hZ2U9c2NfbWV0cmljcyRzbWMpCiMjIFRoZSBzYW1wbGVzIGFyZSB2ZXJ5IHdlbGwgYmVoYXZlZCwgbm9uZSBmYWxsIGJlbG93IHRoZSByZWQgbGluZS4KCnBwKGZpbGU9ImlsbHVzdHJhdG9yX2lucHV0L25vcm1fcGNhLnBkZiIsIGltYWdlPXNjX21ldHJpY3MkcGNhcGxvdCkKIyMgVGhpcyBzaG93cyB1cyB0aGF0IHBlY3VsaWFyIHNwbGl0IGluIGFub3RoZXIgd2F5LiAgVGhhdCBpcyByZWFsbHkgc3RyYW5nZS4KCnBwKGZpbGU9ImlsbHVzdHJhdG9yX2lucHV0L25vcm1fdHNuZS5wZGYiLCBpbWFnZT1zY19tZXRyaWNzJHRzbmVwbG90KQpgYGAKCiMgVHJ5IGEgYmF0Y2ggZXN0aW1hdGlvbgoKSW4gdGhlIGZvbGxvd2luZyBzdGFuemEgSSB3aWxsIGFwcGx5IGEgZmV3IGJhdGNoL3N1cnJvZ2F0ZSBlc3RpbWF0ZXMgaW4gYW4KYXR0ZW1wdCB0byBnZXQgYSBoYW5kbGUgb24gd2hhdCBpcyBnb2luZyBvbiB3aXRoIHRoZXNlIHN0cmFuZ2UgZGF0YSBzcGxpdHMuCgpJbiBlYWNoIGNhc2UgSSB3aWxsIHBsb3QgYSBxdWljayBwY2EgdG8gZ2V0IHNvbWUgaWRlYSBvZiB3aGF0IGhhcHBlbmVkLgoKRm9yIHRoZXNlIGVzdGltYXRlcywgSSB3aWxsIGxlYXZlIG9mZiBjcG0vcXVhbnRpbGUgbm9ybWFsaXphdGlvbnMgdG8gdHJ5IHRvCmlzb2xhdGUgdGhlIGVmZmVjdHMgb2Ygb25seSB0aGUgc3Vycm9nYXRlIGVzdGltYXRlcyBvbiB0aGUgZGF0YS4KCiMjIHN2YSBkZWZhdWx0cwoKU3RhcnQgd2l0aCB0aGUgZGVmYXVsdCB1bnN1cGVydmlzZWQgc3ZhIGVzdGltYXRlLgoKYGBge3IgYmF0Y2hfc3ZhLCBmaWcuc2hvdz0iaGlkZSJ9CnNjMl9zdmEgPC0gc20obm9ybWFsaXplX2V4cHQoc2MyX2V4cHQsIHRyYW5zZm9ybT0ibG9nMiIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsdGVyPVRSVUUsIGJhdGNoPSJzdmEiLCBsb3dfdG9femVybz1UUlVFKSkKc2MyX3N2YV9tZXRyaWNzIDwtIHNtKGdyYXBoX21ldHJpY3Moc2MyX3N2YSkpCmBgYAoKYGBge3IgYmF0Y2hfc3ZhX3BjYX0KcHAoZmlsZT0iaW1hZ2VzL3NjMl9zdmFfcGNhLnBuZyIsIGltYWdlPXNjMl9zdmFfbWV0cmljcyRwY2FwbG90KQojIyBobW0gYmV0dGVyIEkgc3VwcG9zZSwgYnV0IGhwZ2wwNzc0IGlzIDEwMCUga29va3kuCgpwcChmaWxlPSJpbWFnZXMvc2MyX3N2YV90c25lLnBuZyIsIGltYWdlPXNjMl9zdmFfbWV0cmljcyR0c25lcGxvdCkKYGBgCgojIyBmc3ZhCgpUaGlzIGlzIGEgbW9kaWZpY2F0aW9uIG9mIHRoZSBzdmEgZGVmYXVsdHMsIGhlcmUgaXMgYSBxdW90ZSBmcm9tIHRoZQpkb2N1bWVudGF0aW9uOgoKIlRoaXMgZnVuY3Rpb24gcGVyZm9ybXMgZnJvemVuIHN1cnJvZ2F0ZSB2YXJpYWJsZSBhbmFseXNpcyBhcyBkZXNjcmliZWQgaW4KUGFya2VyLCBDb3JyYWRhIEJyYXZvIGFuZCBMZWVrIDIwMTMuIFRoZSBhcHByb2FjaCB1c2VzIGEgdHJhaW5pbmcgZGF0YWJhc2UgdG8KY3JlYXRlIHN1cnJvZ2F0ZSB2YXJpYWJsZXMgd2hpY2ggYXJlIHRoZW4gdXNlZCB0byByZW1vdmUgYmF0Y2ggZWZmZWN0cyBib3RoIGZyb20KdGhlIHRyYWluaW5nIGRhdGFiYXNlIGFuZCBhIG5ldyBkYXRhIHNldCBmb3IgcHJlZGljdGlvbiBwdXJwb3Nlcy4iCgpgYGB7ciBiYXRjaF9mc3ZhLCBmaWcuc2hvdz0iaGlkZSJ9CnNjMl9mc3ZhIDwtIHNtKG5vcm1hbGl6ZV9leHB0KHNjMl9leHB0LCB0cmFuc2Zvcm09ImxvZzIiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWx0ZXI9VFJVRSwgYmF0Y2g9ImZzdmEiKSkKc2MyX2ZzdmFfbWV0cmljcyA8LSBzbShncmFwaF9tZXRyaWNzKHNjMl9mc3ZhKSkKYGBgCgpmc3ZhIHNlZW1zIGxpa2UgaXQgbWlnaHQgYmUgdXNlZnVsLCBidXQgYWxzbyBwb3RlbnRpYWxseSBhIHRvby1sYXJnZQptb2RpZmljYXRpb24gb2YgdGhlIGRhdGEuCgpgYGB7ciBiYXRjaF9mc3ZhX3BjYX0KcHAoZmlsZT0ic2MyX2ZzdmFfcGNhLnBuZyIsIGltYWdlPXNjMl9mc3ZhX21ldHJpY3MkcGNhcGxvdCkKcHAoZmlsZT0ic2MyX2ZzdnNfdHNuZS5wbmciLCBpbWFnZT1zYzJfZnN2YV9tZXRyaWNzJHRzbmVwbG90KQpgYGAKCiMgVmFyaWFuY2UgaHVudGluZwoKSSB3YW50IHRvIGFwcGx5IGEgZmV3IHRvb2xzIHRvIHRyeSB0byBnZXQgYSBoYW5kbGUgb24gd2hlcmUgdGhpcyBzdHJhbmdlCnZhcmlhbmNlIGlzIGNvbWluZyBmcm9tLgoKYGBge3IgdmFyaWFuY2VfaHVudCwgZXZhbD1GQUxTRX0KdmFyaHVudCA8LSBwY2FfaW5mb3JtYXRpb24oZXhwdF9kYXRhPXNjMl9leHB0LAogICAgICAgICAgICAgICAgICAgICAgICAgICBleHB0X2ZhY3RvcnM9YygiY29uZGl0aW9uIiwiYmF0Y2giLCJvcmlnaW5hbGJhdGNoIiwgImluY3ViYXRpb250aW1lIikpCnZhcmh1bnQkYW5vdmFfZnN0YXRfaGVhdG1hcAojIyBCb3RoIGJhdGNoIGVzdGltYXRlcyBhcmUgdmVyeSBzdHJvbmcgb24gUEMxIGFuZCBQQzIsIGluY3ViYXRpb24gdGltZSBjb21lcyBvdXQgb24gdGhlIDNyZCBQQy4KIyMgVGhlIGNvbmRpdGlvbiBsb29rcyBsaWtlIGl0IGlzIHN0dWNrIHdpdGggd2l0aCwgdW5mb3J0dW5hdGVseS4KCnNjMl92YXJwYXJ0IDwtIHZhcnBhcnQoZXhwdD1zYzJfZXhwdCwgcHJlZGljdG9yPU5VTEwsCiAgICAgICAgICAgICAgICAgICAgICAgZmFjdG9ycz1jKCJjb25kaXRpb24iLCJiYXRjaCIsIm9yaWdpbmFsYmF0Y2giLCAiaW5jdWJhdGlvbnRpbWUiKSkKc2MyX3ZhcnBhcnQkcGFydGl0aW9uX3Bsb3QKIyMgV2VsbCBoZXJlIGF0IGxlYXN0LCBpdCBsb29rcyBsaWtlIGJhdGNoIGtpY2tzIGFzcy4KYGBgCgojIFdyaXRlIHRoZSBleHB0CgpMZXQgdXMgYXBwbHkgdGhlIHNhbWUgc2V0IG9mIG5vcm1hbGl6YXRpb25zL3N1cnJvZ2F0ZSBlc3RpbWF0ZXMgYW5kIHdyaXRlIG91dAp0aGUgcmVzdWx0aW5nIHRhYmxlcy4KCmBgYHtyIGZzdmFfd3JpdHRlbiwgZXZhbD1GQUxTRX0KZnVuIDwtIHdyaXRlX2V4cHQoc2MyX2V4cHQsIGV4Y2VsPXBhc3RlMCgiZXhjZWwvc2FtcGxlc193cml0dGVuLXYiLCB2ZXIsICIueGxzeCIpLAogICAgICAgICAgICAgICAgICBmaWx0ZXI9VFJVRSwgbm9ybT0icmF3IiwgYmF0Y2g9ImZzdmEiLCB0cmFuc2Zvcm09ImxvZzIiLCB2aW9saW49VFJVRSkKYGBgCgpgYGB7ciBzYXZlbWV9CmlmICghaXNUUlVFKGdldDAoInNraXBfbG9hZCIpKSkgewogIHBhbmRlcjo6cGFuZGVyKHNlc3Npb25JbmZvKCkpCiAgbWVzc2FnZShwYXN0ZTAoIlRoaXMgaXMgaHBnbHRvb2xzIGNvbW1pdDogIiwgZ2V0X2dpdF9jb21taXQoKSkpCiAgdGhpc19zYXZlIDwtIHBhc3RlMChnc3ViKHBhdHRlcm49IlxcLlJtZCIsIHJlcGxhY2U9IiIsIHg9cm1kX2ZpbGUpLCAiLXYiLCB2ZXIsICIucmRhLnh6IikKICB0bXAgPC0gc20oc2F2ZW1lKGZpbGVuYW1lPXRoaXNfc2F2ZSkpCn0KYGBgCg==