No id variables; using all as measure variables

df = melt(logCount, variable.name = "Sample", value.name ="log2Counts")
df = data.frame(df, Condition = substr(df$Sample, 1, 4))
plotDensityPlot(df)

Using rlog

In this section we make use of log2-transformed counts such that they are normalized with respect to the library size to check for outliers.

No id variables; using all as measure variables

Density plots

No id variables; using all as measure variables

plotDensityPlot(df) + facet_wrap(~ Condition) 

PCA plot

The separation only occurs along the second PC which explains only 16% variance.

MDS plot

Heat map clusters (CTRLx,KDx)

Cook’s Distance

Cook’s distance measures how much a single sample is influencing the fitted coefficients for a gene. A large value of Cook’s distance is intended to indicate an outlier count.

P-value histogram

Close to unifrom distribution. Only 4 DE genes.

Batch-effects correction

I take two strategies:

  1. Model the batch as a covariate in design matrix
  2. Surrogate variable analysis, with using the batch numbers(n=3) as surrogate variables.

Batch as a covariate

estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing

PCA after removing batch-effects

MDS post correction

Heatmap post correction

pvalue distribution post correction

Post batch-effect removal DE genes

log2 fold change (MAP): condition knockdown vs control 
Wald test p-value: condition knockdown vs control 
DataFrame with 13 rows and 6 columns
                  baseMean log2FoldChange      lfcSE       stat       pvalue         padj
                 <numeric>      <numeric>  <numeric>  <numeric>    <numeric>    <numeric>
ENSG00000066044  1817.5801     -1.9609248  0.1148421 -17.074959 2.279873e-65 1.589755e-61
ENSG00000112118  7134.5231     -0.5752556  0.0968824  -5.937669 2.891032e-09 1.007958e-05
ENSG00000149591  1339.1282      0.6779845  0.1184221   5.725153 1.033406e-08 2.401981e-05
ENSG00000131016  9669.6350      0.6474830  0.1165783   5.554060 2.791091e-08 4.865569e-05
ENSG00000109685   823.6079     -0.5608532  0.1112324  -5.042176 4.602675e-07 6.418890e-04
...                    ...            ...        ...        ...          ...          ...
ENSG00000198734  3086.3205     -0.4585079 0.10363208  -4.424382 9.671892e-06  0.007493567
ENSG00000055950  1138.7960     -0.4578538 0.10604262  -4.317640 1.577065e-05  0.010996873
ENSG00000006327  2649.3016      0.4457607 0.10487255   4.250499 2.132947e-05  0.013520946
ENSG00000143632   521.2588      0.4913019 0.12127315   4.051201 5.095549e-05  0.029609386
ENSG00000171345 13738.2914      0.3671011 0.09290258   3.951463 7.767492e-05  0.041663634

Surrogate variable analysis

estimating size factors
estimating dispersions
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing
Number of significant surrogate variables is:  3 
Iteration (out of 5 ):1  2  3  4  5  

Surrogate variables are not really helpful here. If we have a sense of batches of the samples, the plots above should have helped differentiate between different batches, but they do not.

using pre-existing size factors
estimating dispersions
found already estimated dispersions, replacing these
gene-wise dispersion estimates
mean-dispersion relationship
final dispersion estimates
fitting model and testing

Post SVA DE genes

log2 fold change (MAP): condition knockdown vs control 
Wald test p-value: condition knockdown vs control 
DataFrame with 31 rows and 6 columns
                 baseMean log2FoldChange      lfcSE      stat       pvalue         padj
                <numeric>      <numeric>  <numeric> <numeric>    <numeric>    <numeric>
ENSG00000131016  9669.635      0.7648242 0.08088850  9.455290 3.221275e-21 1.293664e-17
ENSG00000112118  7134.523     -0.5807088 0.08363440 -6.943421 3.827170e-12 7.107443e-09
ENSG00000185130  6960.769     -0.5720435 0.08294031 -6.897050 5.309345e-12 7.107443e-09
ENSG00000149591  1339.128      0.6087591 0.09780138  6.224442 4.832715e-10 4.852046e-07
ENSG00000118785 24833.763     -0.4771785 0.07875791 -6.058801 1.371396e-09 1.101506e-06
...                   ...            ...        ...       ...          ...          ...
ENSG00000184260  3863.060     -0.3278997 0.08739693 -3.751844 0.0001755385   0.02610972
ENSG00000132031  4133.702      0.3170201 0.08615926  3.679466 0.0002337225   0.03352249
ENSG00000103187  1104.136     -0.3556372 0.09707397 -3.663569 0.0002487248   0.03444410
ENSG00000131781  1366.976      0.3593298 0.09851680  3.647396 0.0002649116   0.03546284
ENSG00000124145  3137.096      0.3206582 0.08821679  3.634888 0.0002781013   0.03602757
LS0tCnRpdGxlOiAiRXhwbG9yYXRvcnkgQW5hbHlzaXMgSHVSIEh1bWFuIFJpYm8tU2VxKFBlbmFsdmFfTF8wMTE4MjAxNykiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgZmlnX2NhcHRpb246IHllcwogICAgdG9jOiB5ZXMKICBodG1sX2RvY3VtZW50OgogICAgZmlnX2NhcHRpb246IHllcwogIHBkZl9kb2N1bWVudDoKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIHRvYzogeWVzCmRhdGU6ICIwMi8yOC8yMDE3IgotLS0KCiAgIAoKCmBgYHtyLCBlY2hvPUZBTFNFfQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkocmVhZHIpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkoREVTZXEyKSkKc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KFJDb2xvckJyZXdlcikpCnN1cHByZXNzTWVzc2FnZXMobGlicmFyeShnZ3Bsb3QyKSkKc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KEJpb2NQYXJhbGxlbCkpCnN1cHByZXNzTWVzc2FnZXMobGlicmFyeShwaGVhdG1hcCkpCnN1cHByZXNzTWVzc2FnZXMobGlicmFyeShzdmEpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkocmVzaGFwZTIpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkobWl4T21pY3MpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkoZWRnZVIpKQpzdXBwcmVzc01lc3NhZ2VzKGxpYnJhcnkoRURBU2VxKSkKc3VwcHJlc3NNZXNzYWdlcyhsaWJyYXJ5KGNvd3Bsb3QpKQoKcmVnaXN0ZXIoTXVsdGljb3JlUGFyYW0oOCkpCnNwZWNpZXMgPC0gJ2h1bWFuJwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQogYmFzZV9kaXIgPC0gJy9tZWRpYS9kbmEvSHVSX3Jlc3VsdHMvaHVtYW4vcmliby1zZXEvbWFwcGVkL2NvdW50c19zdHJpY3QvYnlDRFMvJwogIGRlc2lnbl9maWxlIDwtICcvbWVkaWEvZG5hL0h1Ul9yZXN1bHRzL2h1bWFuL3JpYm8tc2VxL3JpYm8tc2VxL2Rlc2lnbi50eHQnCiAgb3V0cHJlZml4IDwtICcvbWVkaWEvZG5hL0h1Ul9yZXN1bHRzL2h1bWFuL3JpYm8tc2VxL0RFX2FuYWx5c2lzL2h1bWFuX2RlX2FuYWx5c2lzJwogIGdlbmVfYW5ub3RhdGlvbnMgPC0gJy9tZWRpYS9kbmEvZ2Vub21lcy9oZzM4L2Fubm90YXRpb24vaGczOF9nZW5lX25hbWVzX3N0cmlwcGVkLnRzdicKICBpbnByZWZpeCA8LSAnQ0RTLmNvdW50cycKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgcmVzdWx0cz0naGlkZScsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpwbG90SGVhdE1hcCA8LSBmdW5jdGlvbihybG9nZGlzdCl7CiAgc2FtcGxlRGlzdHMgPC0gZGlzdCh0KGFzc2F5KHJsb2dkaXN0KSkpCiAgc2FtcGxlRGlzdE1hdHJpeCA8LSBhcy5tYXRyaXgoc2FtcGxlRGlzdHMpCiAgcm93bmFtZXMoc2FtcGxlRGlzdE1hdHJpeCkgPC0gcGFzdGUocmxvZ2Rpc3QkY29uZGl0aW9uLCBjb2xuYW1lcyhybG9nZGlzdCksIHNlcD0iLSIpCiAgY29sbmFtZXMoc2FtcGxlRGlzdE1hdHJpeCkgPC0gTlVMTAogIGNvbG9ycyA8LSBjb2xvclJhbXBQYWxldHRlKCByZXYoYnJld2VyLnBhbCg5LCAiQmx1ZXMiKSkgKSgyNTUpCiAgcGhlYXRtYXAoc2FtcGxlRGlzdE1hdHJpeCwKICAgICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX3Jvd3M9c2FtcGxlRGlzdHMsCiAgICAgICAgICBjbHVzdGVyaW5nX2Rpc3RhbmNlX2NvbHM9c2FtcGxlRGlzdHMsCiAgICAgICAgICAgY29sPWNvbG9ycywgbWFpbj1zcGVjaWVzKQp9CmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KcGxvdE1BUGxvdCA8LSBmdW5jdGlvbihERVNlcTJUYWJsZSwgbm9ybWFsaXplPVRSVUUpewogIE1BLmlkeCA9IHQoY29tYm4oMTo2LCAyKSkKICBmb3IoIGkgaW4gIHNlcV9hbG9uZyggTUEuaWR4WywxXSkpeyAKICAgTURQbG90KGNvdW50cyhERVNlcTJUYWJsZSwgbm9ybWFsaXplZCA9IG5vcm1hbGl6ZSksIAogICAgICAgIGMoTUEuaWR4W2ksMV0sTUEuaWR4W2ksMl0pLCAKICAgIG1haW4gPSBwYXN0ZSggY29sbmFtZXMoREVTZXEyVGFibGUpW01BLmlkeFtpLDJdXSwgIiB2cyAiLAogICAgIGNvbG5hbWVzKGRkcylbTUEuaWR4W2ksMV1dICksIHlsaW0gPSBjKC0zLDMpKQogIH0KfQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJywgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CnBsb3REZW5zaXR5UGxvdCA8LSAgZnVuY3Rpb24oZGYpewogIGdncGxvdChkZiwgYWVzKHggPSBsb2cyQ291bnRzLCBjb2xvdXIgPSBTYW1wbGUsIGZpbGwgPSBTYW1wbGUpKSArIHlsaW0oYygwLCAwLjI1KSkgKwogIGdlb21fZGVuc2l0eShhbHBoYSA9IDAuMiwgc2l6ZSA9IDEuMjUpICsKICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAidG9wIikgKyB4bGFiKGV4cHJlc3Npb24obG9nWzJdKGNvdW50ICsgMSkpKQp9CmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0KcGxvdEJhcnMgPC0gZnVuY3Rpb24obG9nRGF0YSl7CiAgZGYgPSBtZWx0KGxvZ0RhdGEsIHZhcmlhYmxlLm5hbWUgPSAiU2FtcGxlIiwgdmFsdWUubmFtZSA9ImxvZzJDb3VudHMiKQogIGRmID0gZGF0YS5mcmFtZShkZiwgQ29uZGl0aW9uID0gc3Vic3RyKGRmJFNhbXBsZSwgMSwgNCkpCiAgZ2dwbG90KGRmLCBhZXMoeCA9IFNhbXBsZSwgeSA9IGxvZzJDb3VudHMsIGZpbGwgPSBDb25kaXRpb24pKSArIGdlb21fYm94cGxvdCgpICsgeGxhYigiIikgKwogIHlsYWIoZXhwcmVzc2lvbihsb2dbMl0oY291bnQgKyAxKSkpIAogICMrIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiM2MTlDRkYiLCAiI0Y1NjRFMyIpKQp9CmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRSwgbWVzc2FnZT1GQUxTRX0KZ2VuZV9hbm5vdGF0aW9ucyA8LSByZWFkLnRhYmxlKGdlbmVfYW5ub3RhdGlvbnMsIHJvdy5uYW1lcyA9IDEsIGNvbC5uYW1lcyA9IGMoJ2lkJywgJ25hbWUnLCAndHlwZScpKQojZGVzaWduLmluZm8gPC0gcmVhZC5jc3YoZGVzaWduX2ZpbGUsIGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmJhdGNoX2Rlc2lnbl9maWxlIDwtICcvbWVkaWEvZG5hL0h1Ul9yZXN1bHRzL2h1bWFuL3JpYm8tc2VxL3JpYm8tc2VxL2Rlc2lnbl9iYXRjaC50eHQnCmRlc2lnbi5pbmZvIDwtIHJlYWQuY3N2KGJhdGNoX2Rlc2lnbl9maWxlLCBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFKQoKc2FtcGxlX2lkIDwtIGRlc2lnbi5pbmZvJHNhbXBsZQpmaWxlcyA8LSBwYXN0ZShzYW1wbGVfaWQsIGlucHJlZml4LCAndHN2Jywgc2VwPScuJykKbmFtZXMoZmlsZXMpIDwtIHNhbXBsZV9pZApjb25kaXRpb24gPC0gYXMuZmFjdG9yKGRlc2lnbi5pbmZvJGNvbmRpdGlvbikKYmF0Y2ggPC0gYXMuZmFjdG9yKGRlc2lnbi5pbmZvJGJhdGNoKQoKc2FtcGxlVGFibGUgPC0gZGF0YS5mcmFtZShzYW1wbGVOYW1lPXNhbXBsZV9pZCwgZmlsZU5hbWU9ZmlsZXMsIGNvbmRpdGlvbiA9IGNvbmRpdGlvbikKZGRzSFRTZXEgPC0gREVTZXFEYXRhU2V0RnJvbUhUU2VxQ291bnQoc2FtcGxlVGFibGU9c2FtcGxlVGFibGUsIGRpcmVjdG9yeT1iYXNlX2RpciwgZGVzaWduPX5jb25kaXRpb24pCgojIyBXZSBkb250IG5lZWQgdmVyc2lvbiBudW1iZXJzCmRkc0hUU2VxIDwtIGRkc0hUU2VxWyByb3dTdW1zKGNvdW50cyhkZHNIVFNlcSkpID4gMSwgIF0Kcm93bmFtZXMoZGRzSFRTZXEpIDwtIGdzdWIoJ1xcLlswLTldKycsICcnLCByb3duYW1lcyhkZHNIVFNlcSkpCmNvbERhdGEoZGRzSFRTZXEpJGNvbmRpdGlvbjwtZmFjdG9yKGNvbERhdGEoZGRzSFRTZXEpJGNvbmRpdGlvbiwgbGV2ZWxzPWMoJ2NvbnRyb2wnLCdrbm9ja2Rvd24nKSkKCmRkcyA8LSBERVNlcShkZHNIVFNlcSkKCnJhd0NvdW50VGFibGUgPC0gYXMuZGF0YS5mcmFtZShhc3NheXMoZGRzSFRTZXEpJGNvdW50cykKY29sdW1uLm5hbWVzIDwtIGMoJ0NUUkwxJywgJ0NUUkwyJyAsICdDVFJMNicsICdLRDEnLCAnS0QyJywgJ0tENicpCmNvbG5hbWVzKHJhd0NvdW50VGFibGUpIDwtIGNvbHVtbi5uYW1lcwoKZGRzMSA8LSBERVNlcShkZHNIVFNlcSkKcmVzMSA8LSByZXN1bHRzKGRkczEpCnJlc09yZGVyZWQxIDwtIHJlczFbb3JkZXIocmVzMSRwYWRqKSxdCnJlc1NpZzEgPC0gc3Vic2V0KHJlc09yZGVyZWQxLCBwYWRqIDwgMC4wNSkKYGBgCgoKYGBge3IsIGVjaG89RkFMU0V9CmxvZ0NvdW50IDwtIGxvZzIocmF3Q291bnRUYWJsZSsxKQpwbG90QmFycyhsb2dDb3VudCkKYGBgCgoKCmBgYHtyLCBtZXNzYWdlPUZBTFNFfQpkZiA9IG1lbHQobG9nQ291bnQsIHZhcmlhYmxlLm5hbWUgPSAiU2FtcGxlIiwgdmFsdWUubmFtZSA9ImxvZzJDb3VudHMiKQpkZiA9IGRhdGEuZnJhbWUoZGYsIENvbmRpdGlvbiA9IHN1YnN0cihkZiRTYW1wbGUsIDEsIDQpKQpwbG90RGVuc2l0eVBsb3QoZGYpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnBsb3REZW5zaXR5UGxvdChkZikgKyBmYWNldF93cmFwKH4gQ29uZGl0aW9uKQpgYGAKCgojIyBVc2luZyBybG9nCkluIHRoaXMgc2VjdGlvbiB3ZSBtYWtlIHVzZSBvZiBsb2cyLXRyYW5zZm9ybWVkIGNvdW50cyBzdWNoIHRoYXQgdGhleSBhcmUgbm9ybWFsaXplZCB3aXRoIHJlc3BlY3QgdG8gdGhlIGxpYnJhcnkgc2l6ZSB0byBjaGVjayBmb3Igb3V0bGllcnMuCgpgYGB7ciwgZWNobz1GQUxTRSAsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpybGQ8LSBybG9nVHJhbnNmb3JtYXRpb24oZGRzLCBibGluZD1UUlVFKQpsb2dDb3VudCA8LSBhcy5kYXRhLmZyYW1lKGFzc2F5KHJsZCkpCmNvbG5hbWVzKGxvZ0NvdW50KSA8LSBjb2x1bW4ubmFtZXMKcGxvdEJhcnMobG9nQ291bnQpCmBgYCAKCiMjIERlbnNpdHkgcGxvdHMKCgpgYGB7ciwgZWNobz1GQUxTRSAsIHdhcm5pbmc9RkFMU0UsIGVycm9yPUZBTFNFfQpkZiA9IG1lbHQobG9nQ291bnQsIHZhcmlhYmxlLm5hbWUgPSAiU2FtcGxlIiwgdmFsdWUubmFtZSA9ImxvZzJDb3VudHMiKQpkZiA9IGRhdGEuZnJhbWUoZGYsIENvbmRpdGlvbiA9IHN1YnN0cihkZiRTYW1wbGUsIDEsIDQpKQpwbG90RGVuc2l0eVBsb3QoZGYpCmBgYAoKYGBge3IsIGZpZy5jYXA9J0wnfQpwbG90RGVuc2l0eVBsb3QoZGYpICsgZmFjZXRfd3JhcCh+IENvbmRpdGlvbikgCmBgYAoKCiMjIFBDQSBwbG90CgpUaGUgc2VwYXJhdGlvbiBvbmx5IG9jY3VycyBhbG9uZyB0aGUgc2Vjb25kIFBDIHdoaWNoIGV4cGxhaW5zIG9ubHkgMTYlIHZhcmlhbmNlLgoKCmBgYHtyLCBlY2hvPUZBTFNFfQpydiA9IHJvd1ZhcnMobG9nQ291bnQpCnNlbGVjdCA9IG9yZGVyKHJ2LCBkZWNyZWFzaW5nID0gVFJVRSlbMTo1MDBdCnBjYSA9IHByY29tcCh0KGxvZ0NvdW50W3NlbGVjdCwgXSkpCgpgYGAKCgpgYGB7ciwgZWNobz1GQUxTRX0KcGxvdFBDQShybGQsIGludGdyb3VwID0gYygiY29uZGl0aW9uIikpKyBnZ3RpdGxlKHNwZWNpZXMpCmBgYAoKIyMgTURTIHBsb3QKCmBgYHtyLCBlY2hvPUZBTFNFICwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9RkFMU0V9CmZhYyA9IGZhY3Rvcihjb2x1bW4ubmFtZXMpCmNvbG91cnMgPSBicmV3ZXIucGFsKG5sZXZlbHMoYXMuZmFjdG9yKGNvbmRpdGlvbikpLCAiUGFpcmVkIikKcGxvdE1EUyhsb2dDb3VudCwgY29sID0gY29sb3Vyc1thcy5udW1lcmljKGFzLmZhY3Rvcihjb25kaXRpb24pKV0sIGxhYmVscyA9IGZhYywgbWFpbj0nTURTIHBsb3Qgb2YgcmxvZ1RyYW5zZm9ybWF0aW9uKGNvdW50cyknKSMrIGdndGl0bGUoc3BlY2llcykKYGBgCgoKYGBge3IsIGVjaG89RkFMU0UgLCB3YXJuaW5nPUZBTFNFLCBlcnJvcj1GQUxTRX0Kc2FtcGxlRGlzdHMgPC0gZGlzdCggdCggbG9nQ291bnQgKSApCnNhbXBsZURpc3RNYXRyaXggPC0gYXMubWF0cml4KCBzYW1wbGVEaXN0cyApCm1kc0RhdGEgPC0gZGF0YS5mcmFtZShjbWRzY2FsZShzYW1wbGVEaXN0TWF0cml4KSkKbWRzIDwtIGNiaW5kKG1kc0RhdGEsIGFzLmRhdGEuZnJhbWUoY29sRGF0YShybGQpKSkKZ2dwbG90KG1kcywgYWVzKFgxLFgyLGNvbG9yPWNvbmRpdGlvbiwgc2hhcGU9YmF0Y2gpKSArIGdlb21fcG9pbnQoc2l6ZT0zKSArCiAgY29vcmRfZml4ZWQoKSsgZ2d0aXRsZShzcGVjaWVzKQoKYGBgCiMjIEhlYXQgbWFwIGNsdXN0ZXJzIChDVFJMeCxLRHgpCgoKYGBge3IsIGVjaG89RkFMU0V9CnBsb3RIZWF0TWFwKHJsZCkKYGBgCgojIyBDb29rJ3MgRGlzdGFuY2UKCgogQ29va+KAmXMgZGlzdGFuY2UgbWVhc3VyZXMgaG93IG11Y2ggYSBzaW5nbGUgc2FtcGxlIGlzIGluZmx1ZW5jaW5nIHRoZSBmaXR0ZWQgY29lZmZpY2llbnRzIGZvciBhIGdlbmUuIEEgbGFyZ2UgdmFsdWUgb2YKQ29va+KAmXMgZGlzdGFuY2UgaXMgaW50ZW5kZWQgdG8gaW5kaWNhdGUgYW4gb3V0bGllciBjb3VudC4KCmBgYHtyLCBlY2hvPUZBTFNFICwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0V9CnBhcihtYXI9Yyg4LDUsMiwyKSkKYm94cGxvdChsb2cxMChhc3NheXMoZGRzKVtbImNvb2tzIl1dKSwgcmFuZ2U9MCwgbGFzPTIsIG1haW49IkNvb2sncyBkaXN0YW5jZSIpCmBgYAoKCgojIyBQLXZhbHVlIGhpc3RvZ3JhbQpgYGB7ciwgZWNobz1GQUxTRX0KcXBsb3QocHZhbHVlLCBkYXRhPWFzLmRhdGEuZnJhbWUocmVzMSksIGdlb209J2hpc3RvZ3JhbScsIGJpbndpZHRoPTAuMDUpCmBgYApDbG9zZSB0byB1bmlmcm9tIGRpc3RyaWJ1dGlvbi4gT25seSA0IERFIGdlbmVzLgoKCmBgYHtyLCBlY2hvPUZBTFNFICwgd2FybmluZz1GQUxTRSwgZXJyb3I9RkFMU0UsIGV2YWw9RkFMU0V9CmZhYyA9IGZhY3Rvcihjb2x1bW4ubmFtZXMpCnBsb3RNRFMobG9nKGNvdW50cyhkZHMsIG5vcm1hbGl6ZWQ9VFJVRSkgKyAxKSAtIGxvZyh0KCB0KGFzc2F5cyhkZHMpW1sibXUiXV0pIC8gc2l6ZUZhY3RvcnMoZGRzKSApICsgMSksIG1haW49J01EUyBwbG90IG9mIHJsb2dUcmFuc2Zvcm1hdGlvbihjb3VudHMpLWxvZyhtdS9zaXplZmFjdG9yKScsIGNvbCA9IGNvbG91cnNbYXMubnVtZXJpYyhhcy5mYWN0b3IoY29uZGl0aW9uKSldLCBsYWJlbHMgPSBmYWMpCmBgYAoKCiMjIEJhdGNoLWVmZmVjdHMgY29ycmVjdGlvbgoKSSB0YWtlIHR3byBzdHJhdGVnaWVzOgoKMS4gTW9kZWwgdGhlIGJhdGNoIGFzIGEgY292YXJpYXRlIGluIGRlc2lnbiBtYXRyaXgKMi4gU3Vycm9nYXRlIHZhcmlhYmxlIGFuYWx5c2lzLCB3aXRoIHVzaW5nIHRoZSBiYXRjaCBudW1iZXJzKG49MykgYXMgc3Vycm9nYXRlIHZhcmlhYmxlcy4KCgojIyMgQmF0Y2ggYXMgYSBjb3ZhcmlhdGUKCmBgYHtyLCBlY2hvPUZBTFNFfQpiYXRjaF9kZXNpZ25fZmlsZSA8LSAnL21lZGlhL2RuYS9IdVJfcmVzdWx0cy9odW1hbi9yaWJvLXNlcS9yaWJvLXNlcS9kZXNpZ25fYmF0Y2gudHh0JwpkZXNpZ24uaW5mbyA8LSByZWFkLmNzdihiYXRjaF9kZXNpZ25fZmlsZSwgaGVhZGVyID0gVFJVRSwgc3RyaW5nc0FzRmFjdG9ycz1GQUxTRSkKZGVzaWduLmluZm8KCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnNhbXBsZV9pZCA8LSBkZXNpZ24uaW5mbyRzYW1wbGUKZmlsZXMgPC0gcGFzdGUoc2FtcGxlX2lkLCBpbnByZWZpeCwgJ3RzdicsIHNlcD0nLicpCm5hbWVzKGZpbGVzKSA8LSBzYW1wbGVfaWQKY29uZGl0aW9uIDwtIGRlc2lnbi5pbmZvJGNvbmRpdGlvbgpiYXRjaCA8LSBkZXNpZ24uaW5mbyRiYXRjaAoKc2FtcGxlVGFibGUgPC0gZGF0YS5mcmFtZShzYW1wbGVOYW1lPXNhbXBsZV9pZCwgZmlsZU5hbWU9ZmlsZXMsIGNvbmRpdGlvbiA9IGNvbmRpdGlvbiwgYmF0Y2g9YmF0Y2gpCmRkc0hUU2VxIDwtIERFU2VxRGF0YVNldEZyb21IVFNlcUNvdW50KHNhbXBsZVRhYmxlPXNhbXBsZVRhYmxlLCBkaXJlY3Rvcnk9YmFzZV9kaXIsIGRlc2lnbj1+YmF0Y2grY29uZGl0aW9uKQpyb3duYW1lcyhkZHNIVFNlcSkgPC0gZ3N1YignXFwuWzAtOV0rJywgJycsIHJvd25hbWVzKGRkc0hUU2VxKSkKZGRzSFRTZXEgPC0gZGRzSFRTZXFbIHJvd1N1bXMoY291bnRzKGRkc0hUU2VxKSkgPiAxLCAgXQoKY29sRGF0YShkZHNIVFNlcSkkY29uZGl0aW9uPC1mYWN0b3IoY29sRGF0YShkZHNIVFNlcSkkY29uZGl0aW9uLCBsZXZlbHM9YygnY29udHJvbCcsJ2tub2NrZG93bicpKQpjb2xEYXRhKGRkc0hUU2VxKSRiYXRjaDwtZmFjdG9yKGNvbERhdGEoZGRzSFRTZXEpJGJhdGNoLCBsZXZlbHM9YygnQjEnLCdCMicsICdCMycpKQoKZGRzMyA8LSBERVNlcShkZHNIVFNlcSkKcmVzMyA8LSByZXN1bHRzKGRkczMpCnJlc09yZGVyZWQzIDwtIHJlczNbb3JkZXIocmVzMyRwYWRqKSxdCnJlc1NpZzMgPC0gc3Vic2V0KHJlc09yZGVyZWQzLCBwYWRqIDwgMC4wNSkKCnJhd0NvdW50VGFibGUgPC0gYXMuZGF0YS5mcmFtZShhc3NheXMoZGRzSFRTZXEpJGNvdW50cykKY29sdW1uLm5hbWVzIDwtIGMoJ0NUUkwxJywgJ0NUUkwyJyAsICdDVFJMNicsICdLRDEnLCAnS0QyJywgJ0tENicpCmNvbG5hbWVzKHJhd0NvdW50VGFibGUpIDwtIGNvbHVtbi5uYW1lcwoKYGBgCgojIyBQQ0EgYWZ0ZXIgcmVtb3ZpbmcgYmF0Y2gtZWZmZWN0cwpgYGB7ciwgZWNobz1GQUxTRX0KcmxkMyA8LSBybG9nVHJhbnNmb3JtYXRpb24oZGRzMywgYmxpbmQ9VFJVRSkKYXNzYXkocmxkMykgPC0gbGltbWE6OnJlbW92ZUJhdGNoRWZmZWN0KGFzc2F5KHJsZCksIHJsZDMkYmF0Y2gpCnBsb3RQQ0EocmxkMywgYygiY29uZGl0aW9uIikpCmBgYAoKIyMgTURTIHBvc3QgY29ycmVjdGlvbgpgYGB7ciwgZWNobz1GQUxTRX0KCmxvZ0NvdW50MyA8LSBhcy5kYXRhLmZyYW1lKGFzc2F5KHJsZDMpKQpzYW1wbGVEaXN0cyA8LSBkaXN0KCB0KCBsb2dDb3VudDMgKSApCnNhbXBsZURpc3RNYXRyaXggPC0gYXMubWF0cml4KCBzYW1wbGVEaXN0cyApCm1kc0RhdGEgPC0gZGF0YS5mcmFtZShjbWRzY2FsZShzYW1wbGVEaXN0TWF0cml4KSkKbWRzIDwtIGNiaW5kKG1kc0RhdGEsIGFzLmRhdGEuZnJhbWUoY29sRGF0YShybGQzKSkpCmdncGxvdChtZHMsIGFlcyhYMSxYMixjb2xvcj1jb25kaXRpb24sIHNoYXBlPWJhdGNoKSkgKyBnZW9tX3BvaW50KHNpemU9MykgKwogIGNvb3JkX2ZpeGVkKCkrIGdndGl0bGUoc3BlY2llcykKYGBgCgojIyBIZWF0bWFwIHBvc3QgY29ycmVjdGlvbgpgYGB7ciwgZWNobz1GQUxTRX0KcGxvdEhlYXRNYXAocmxkMykKYGBgCgojIyMgcHZhbHVlIGRpc3RyaWJ1dGlvbiBwb3N0IGNvcnJlY3Rpb24KYGBge3IsIGVjaG89RkFMU0V9CnFwbG90KHB2YWx1ZSwgZGF0YT1hcy5kYXRhLmZyYW1lKHJlczMpLCBnZW9tPSdoaXN0b2dyYW0nLCBiaW53aWR0aD0wLjA1KQpgYGAKCiMjIFBvc3QgYmF0Y2gtZWZmZWN0IHJlbW92YWwgREUgZ2VuZXMKYGBge3IsIGVjaG89RkFMU0V9CnJlc1NpZzMKYGBgCgojIyMgU3Vycm9nYXRlIHZhcmlhYmxlIGFuYWx5c2lzCgpgYGB7ciwgZWNobz1GQUxTRX0KCnNhbXBsZV9pZCA8LSBkZXNpZ24uaW5mbyRzYW1wbGUKZmlsZXMgPC0gcGFzdGUoc2FtcGxlX2lkLCBpbnByZWZpeCwgJ3RzdicsIHNlcD0nLicpCm5hbWVzKGZpbGVzKSA8LSBzYW1wbGVfaWQKY29uZGl0aW9uIDwtIGRlc2lnbi5pbmZvJGNvbmRpdGlvbgpiYXRjaCA8LSBhcy5mYWN0b3IoZGVzaWduLmluZm8kYmF0Y2gpCgpzYW1wbGVUYWJsZSA8LSBkYXRhLmZyYW1lKHNhbXBsZU5hbWU9c2FtcGxlX2lkLCBmaWxlTmFtZT1maWxlcywgY29uZGl0aW9uID0gY29uZGl0aW9uLCBiYXRjaD1iYXRjaCkKZGRzSFRTZXEgPC0gREVTZXFEYXRhU2V0RnJvbUhUU2VxQ291bnQoc2FtcGxlVGFibGU9c2FtcGxlVGFibGUsIGRpcmVjdG9yeT1iYXNlX2RpciwgZGVzaWduPX5jb25kaXRpb24pCnJvd25hbWVzKGRkc0hUU2VxKSA8LSBnc3ViKCdcXC5bMC05XSsnLCAnJywgcm93bmFtZXMoZGRzSFRTZXEpKQpkZHNIVFNlcSA8LSBkZHNIVFNlcVsgcm93U3Vtcyhjb3VudHMoZGRzSFRTZXEpKSA+IDEsICBdCgpjb2xEYXRhKGRkc0hUU2VxKSRjb25kaXRpb248LWZhY3Rvcihjb2xEYXRhKGRkc0hUU2VxKSRjb25kaXRpb24sIGxldmVscz1jKCdjb250cm9sJywna25vY2tkb3duJykpCmNvbERhdGEoZGRzSFRTZXEpJGJhdGNoPC1mYWN0b3IoY29sRGF0YShkZHNIVFNlcSkkYmF0Y2gsIGxldmVscz1jKCdCMScsJ0IyJywgJ0IzJykpCgpkZHMyIDwtIERFU2VxKGRkc0hUU2VxKQoKZGF0IDwtIGNvdW50cyhkZHMyLCBub3JtYWxpemVkPVRSVUUpCmlkeCA8LSByb3dNZWFucyhkYXQpID4gMQpkYXQgPC0gZGF0W2lkeCxdCm1vZCA8LSBtb2RlbC5tYXRyaXgofiBjb25kaXRpb24sIGNvbERhdGEoZGRzMikpCm1vZDAgPC0gbW9kZWwubWF0cml4KH4gMSwgY29sRGF0YShkZHMyKSkKc3ZzZXEgPC0gc3Zhc2VxKGRhdCwgbW9kLCBtb2QwLCBuLnN2PTMpCmRkczIkYmF0Y2ggPC0gYmF0Y2gKc3RyaXBjaGFydChzdnNlcSRzdlssMV0gfiBkZHMyJGJhdGNoLHZlcnRpY2FsPVRSVUUsbWFpbj0iU1YxIikKYWJsaW5lKGg9MCkKc3RyaXBjaGFydChzdnNlcSRzdlssMl0gfiBkZHMyJGJhdGNoLHZlcnRpY2FsPVRSVUUsbWFpbj0iU1YyIikKYWJsaW5lKGg9MCkKc3RyaXBjaGFydChzdnNlcSRzdlssM10gfiBkZHMyJGJhdGNoLHZlcnRpY2FsPVRSVUUsbWFpbj0iU1YzIikKYWJsaW5lKGg9MCkKcGxvdChzdnNlcSRzdlssMV0sIHN2c2VxJHN2WywyXSwgY29sPWRkczIkYmF0Y2gsIHBjaD0xNikKYGBgCgpTdXJyb2dhdGUgdmFyaWFibGVzIGFyZSBub3QgcmVhbGx5IGhlbHBmdWwgaGVyZS4gSWYgd2UgaGF2ZSBhIHNlbnNlIG9mIGJhdGNoZXMgb2YgdGhlIHNhbXBsZXMsIHRoZSBwbG90cyBhYm92ZSBzaG91bGQgaGF2ZSBoZWxwZWQgZGlmZmVyZW50aWF0ZSBiZXR3ZWVuIGRpZmZlcmVudCBiYXRjaGVzLCBidXQgdGhleSBkbyBub3QuCgpgYGB7ciwgZWNobz1GQUxTRX0KZGRzc3ZhIDwtIGRkczIKZGRzc3ZhJFNWMSA8LSBzdnNlcSRzdlssMV0KZGRzc3ZhJFNWMiA8LSBzdnNlcSRzdlssMl0KZGRzc3ZhJFNWMyA8LSBzdnNlcSRzdlssM10KCmRlc2lnbihkZHNzdmEpIDwtIH4gU1YxICsgU1YyICsgU1YzICsgY29uZGl0aW9uCmRkc3N2YSA8LSBERVNlcShkZHNzdmEpCnJlcy5zdmEgPC0gcmVzdWx0cyhkZHNzdmEpCnJlc09yZGVyZWQuc3ZhIDwtIHJlcy5zdmFbb3JkZXIocmVzLnN2YSRwYWRqKSxdCnJlc1NpZy5zdmEgPC0gc3Vic2V0KHJlc09yZGVyZWQuc3ZhLCBwYWRqIDwgMC4wNSkKYGBgCgojIyBQb3N0IFNWQSBERSBnZW5lcwpgYGB7ciwgZWNobz1GQUxTRX0KcmVzU2lnLnN2YQpgYGA=