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:
- Model the batch as a covariate in design matrix
- 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=