DE for Eed-cKO vs WT on FB, MB, HB, SC
In this notebook we test for differential expression between and WT tissues in the developing mouse CNS.
Each condition (WT, , for FB, MB, HB, and SC) contains six samples (two replicates at e13.5, e15.5, and e18).
For this analysis, we are not interested in the effects of time and thus add in the time factor to our DE (linear) model as a batch correction factor.
Script setup
Run DE on each tissue
Here we run the DE analysis on each tissue for the comparison.
runDeseq2BetweenCond(paste('merged_df_fb_FEATURE_COUNTS_', date, '.csv', sep=''), paste('DEseq2_CNS_fb_', date, '.csv', sep=''))
[1] "========================== RUNNING merged_df_fb_FEATURE_COUNTS_20210124.csv ============================"
[1] "Dataset dimensions: 15304 12"
estimating size factors
estimating dispersions
gene-wise dispersion estimates
Normalise the data
filename <- paste(project_dir, 'merged_df_FEATURE_COUNTS_', date, '.csv', sep='')
# https://bioconductor.org/packages/release/workflows/vignettes/rnaseqGene/inst/doc/rnaseqGene.html
counts <- read.csv(filename, header = TRUE, sep = ",")
rownames(counts) <- counts$entrezgene_id
genes <- counts$entrezgene_id
# Let's make sure our count data is in matrix format and is only the numeric columns i.e. everything but the genes
counts <- counts[,2:ncol(counts)]
counts[is.na(counts)] = 0
# Here we get the names of the columns, for my stuff I always have all the info in one string as I find it makes it easier
# this means each of the "groups" are separated by a "_" this may be different for you
sampleNames <- colnames(counts) # Sample names
# For DEseq2 we need to turn this into a dataframe
sampleDF = data.frame(sampleNames = sampleNames)
# Make sure we don't include the ID in our columns
countMatrix <- as.matrix(counts)
# We now set the row names to be the gene IDs
rownames(countMatrix) <- genes
ddsMat <- DESeqDataSetFromMatrix(countData = countMatrix,
colData = sampleDF,
design = ~ 1)
dds <- estimateSizeFactors(ddsMat)
outputFilename <- paste(project_dir, 'merged_df_FEATURE_COUNTS_DEseq2Norm_', date, '.csv', sep='')
write.csv(counts(dds,normalized=TRUE), file = outputFilename)
rld <- rlog(countMatrix + 1, blind = FALSE)
rlog() may take a long time with 50 or more samples,
vst() is a much faster transformation
converting counts to integer mode
Print session info
sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-apple-darwin17.0 (64-bit)
Running under: macOS Catalina 10.15.5
Matrix products: default
BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.0/Resources/lib/libRlapack.dylib
locale:
[1] en_AU.UTF-8/en_AU.UTF-8/en_AU.UTF-8/C/en_AU.UTF-8/en_AU.UTF-8
attached base packages:
[1] parallel stats4 stats graphics grDevices utils datasets methods base
other attached packages:
[1] edgeR_3.30.3 limma_3.44.3 DESeq2_1.28.1 SummarizedExperiment_1.18.2 DelayedArray_0.14.1
[6] matrixStats_0.58.0 Biobase_2.48.0 GenomicRanges_1.40.0 GenomeInfoDb_1.24.2 IRanges_2.22.2
[11] S4Vectors_0.26.1 BiocGenerics_0.34.0
loaded via a namespace (and not attached):
[1] bitops_1.0-7 bit64_4.0.5 RColorBrewer_1.1-2 rstan_2.21.2 tools_4.0.3 bslib_0.2.5 utf8_1.2.1
[8] R6_2.5.0 DBI_1.1.1 colorspace_2.0-1 withr_2.4.2 tidyselect_1.1.1 gridExtra_2.3 prettyunits_1.1.1
[15] processx_3.5.2 sircle_0.0.0.9000 bit_4.0.4 curl_4.3.1 compiler_4.0.3 cli_2.5.0 sass_0.4.0
[22] scales_1.1.1 genefilter_1.70.0 callr_3.7.0 stringr_1.4.0 digest_0.6.27 StanHeaders_2.21.0-7 rmarkdown_2.8
[29] XVector_0.28.0 pkgconfig_2.0.3 htmltools_0.5.1.1 fastmap_1.1.0 rlang_0.4.11 RSQLite_2.2.7 jquerylib_0.1.4
[36] generics_0.1.0 jsonlite_1.7.2 BiocParallel_1.22.0 dplyr_1.0.6 inline_0.3.18 RCurl_1.98-1.3 magrittr_2.0.1
[43] GenomeInfoDbData_1.2.3 loo_2.4.1 Matrix_1.3-3 Rcpp_1.0.6 munsell_0.5.0 fansi_0.4.2 lifecycle_1.0.0
[50] stringi_1.5.3 yaml_2.2.1 zlibbioc_1.34.0 pkgbuild_1.2.0 grid_4.0.3 blob_1.2.1 crayon_1.4.1
[57] lattice_0.20-44 splines_4.0.3 annotate_1.66.0 locfit_1.5-9.4 knitr_1.33 ps_1.6.0 pillar_1.6.1
[64] geneplotter_1.66.0 codetools_0.2-18 XML_3.99-0.6 glue_1.4.2 evaluate_0.14 V8_3.4.2 RcppParallel_5.1.4
[71] vctrs_0.3.8 gtable_0.3.0 purrr_0.3.4 assertthat_0.2.1 cachem_1.0.5 ggplot2_3.3.3 xfun_0.23
[78] xtable_1.8-4 rsconnect_0.8.17 survival_3.2-11 tibble_3.1.0 AnnotationDbi_1.50.3 memoise_2.0.0 ellipsis_0.3.2
References:
hbctraining/DGE_workshop. Teaching materials at the Harvard Chan Bioinformatics Core, 2021. Accessed: Jun. 15, 2021. [Online]. Available: https://github.com/hbctraining/DGE_workshop
Love MI, Huber W, Anders S (2014). “Moderated estimation of fold change and dispersion for RNA-seq data with DESeq2.” Genome Biology, 15, 550. doi: 10.1186/s13059-014-0550-8.
M. D. Robinson, D. J. McCarthy, and G. K. Smyth, ‘edgeR: a Bioconductor package for differential expression analysis of digital gene expression data’, Bioinformatics, vol. 26, no. 1, pp. 139–140, Jan. 2010, doi: 10.1093/bioinformatics/btp616.
LS0tCnRpdGxlOiAiRWVkLWNLTyB2cyBXVCBjb21wYXJpc29uIEFQLWF4aXMiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQpgYGAKCiMjIERFIGZvciBFZWQtY0tPIHZzIFdUIG9uIEZCLCBNQiwgSEIsIFNDCgpJbiB0aGlzIG5vdGVib29rIHdlIHRlc3QgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGJldHdlZW4gXGVtcGh7RWVkLWNLT30gYW5kIFdUIHRpc3N1ZXMgaW4gdGhlIGRldmVsb3BpbmcgbW91c2UgQ05TLlwKCkVhY2ggY29uZGl0aW9uIChXVCwgXGVtcGh7RWVkLWNLT30sIGZvciBGQiwgTUIsIEhCLCBhbmQgU0MpIGNvbnRhaW5zIHNpeCBzYW1wbGVzICh0d28gcmVwbGljYXRlcyBhdCBlMTMuNSwgZTE1LjUsIGFuZCBlMTgpLlwKCkZvciB0aGlzIGFuYWx5c2lzLCB3ZSBhcmUgbm90IGludGVyZXN0ZWQgaW4gdGhlIGVmZmVjdHMgb2YgdGltZSBhbmQgdGh1cyBhZGQgaW4gdGhlIHRpbWUgZmFjdG9yIHRvIG91ciBERSAobGluZWFyKSBtb2RlbCBhcyBhIGJhdGNoIGNvcnJlY3Rpb24gZmFjdG9yLlwKCgojIyMgU2NyaXB0IHNldHVwCgpgYGB7cn0KbGlicmFyeShERVNlcTIpCgojIEdsb2JhbCB2YXJpYWJsZXMgdG8gbWFrZSBuYW1lIGZvcm1hdHMgY29uc2lzdGVudApwcm9qZWN0X2RpciA8LSAnLi4vZGF0YS9yZXN1bHRzL2Rlc2VxMi8nCmRhdGUgPC0gJzIwMjEwMTI0JwoKcnVuRGVzZXEyQmV0d2VlbkNvbmQgPC0gZnVuY3Rpb24gKGZpbGVuYW1lLCBvdXRwdXRfZmlsZW5hbWUsIHJ1bl90eXBlKSB7CgogICAgZmlsZV9wYXRoIDwtIHBhc3RlKHByb2plY3RfZGlyLCBmaWxlbmFtZSwgc2VwPScnKQogIAogICAgcHJpbnQocGFzdGUoIj09PT09PT09PT09PT09PT09PT09PT09PT09IFJVTk5JTkcgIiwgZmlsZW5hbWUsICIgPT09PT09PT09PT09PT09PT09PT09PT09PT09PSIsIHNlcD0iIikpCiAgICAgICMgaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2Uvd29ya2Zsb3dzL3ZpZ25ldHRlcy9ybmFzZXFHZW5lL2luc3QvZG9jL3JuYXNlcUdlbmUuaHRtbAogICAgY291bnRzIDwtIHJlYWQuY3N2KGZpbGVfcGF0aCwgaGVhZGVyID0gVFJVRSwgc2VwID0gIiwiKQogICAgcm93bmFtZXMoY291bnRzKSA8LSBjb3VudHMkdV9pZAoKICAgICMgTGV0J3MgbWFrZSBzdXJlIG91ciBjb3VudCBkYXRhIGlzIGluIG1hdHJpeCBmb3JtYXQgYW5kIGlzIG9ubHkgdGhlIG51bWVyaWMgY29sdW1ucyBpLmUuIGV2ZXJ5dGhpbmcgYnV0IHRoZSBnZW5lcwogICAgY291bnRzIDwtIGNvdW50c1ssMjpuY29sKGNvdW50cyldCgogICAgc2FtcGxlX25hbWVzIDwtIGNvbG5hbWVzKGNvdW50cykgIyBTYW1wbGUgbmFtZXMKICAgIAogICAgIyBNYWtlIHN1cmUgd2UgZG9uJ3QgaW5jbHVkZSB0aGUgSUQgaW4gb3VyIGNvbHVtbnMKICAgIGNvdW50X21hdHJpeCA8LSBhcy5tYXRyaXgoY291bnRzKQogICAgCiAgICAjIFdlIG5vdyBzZXQgdGhlIHJvdyBuYW1lcyB0byBiZSB0aGUgZ2VuZSBJRHMKICAgIHJvd25hbWVzKGNvdW50X21hdHJpeCkgPC0gcm93bmFtZXMoY291bnRzKSAKICAgIAogICAgIyBTZXBhcmF0ZSBvdXQgZWFjaCBvZiB0aGUgc2FtcGxlIG5hbWVzIHRvIGJlIHRoZSBkaWZmZXJlbnQgZXhwZXJpbWVudCBjb25kaXRpb25zCiAgICBjb25kaXRpb24gPC0gZmFjdG9yKHNhcHBseShzYW1wbGVfbmFtZXMsIGZ1bmN0aW9uKHgpe3N1YnN0cih4LCBzdGFydCA9IDEsIHN0b3AgPSAyKX0pKQogICAgdGltZSA8LSBmYWN0b3Ioc2FwcGx5KHNhbXBsZV9uYW1lcywgZnVuY3Rpb24oeCl7c3Vic3RyKHgsIHN0YXJ0ID0gMywgc3RvcCA9IDQpfSkpCiAgICB0aXNzdWUgPC0gZmFjdG9yKHNhcHBseShzYW1wbGVfbmFtZXMsIGZ1bmN0aW9uKHgpe3N1YnN0cih4LCBzdGFydCA9IDUsIHN0b3AgPSA2KX0pKQogICAgY29uZGl0aW9uX2lkIDwtIGZhY3RvcihzYXBwbHkoc2FtcGxlX25hbWVzLCBmdW5jdGlvbih4KXtpZiAoZ3JlcGwoImtvIiwgeCwgZml4ZWQgPSBUUlVFKSkgezF9IGVsc2UgezB9fSkpCgogICAgIyBGb3IgREVzZXEyIHdlIG5lZWQgdG8gdHVybiB0aGlzIGludG8gYSBkYXRhZnJhbWUgCiAgICBzYW1wbGVfZGYgPSBkYXRhLmZyYW1lKHNhbXBsZV9uYW1lcyA9IHNhbXBsZV9uYW1lcywgY29uZGl0aW9uID0gY29uZGl0aW9uLCB0aW1lID0gdGltZSwgdGlzc3VlID0gdGlzc3VlLCBjb25kaXRpb25faWQ9Y29uZGl0aW9uX2lkKQogICAgZGRzX21hdCA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50X21hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbERhdGEgPSBzYW1wbGVfZGYsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+dGltZStjb25kaXRpb25faWQpICMgSGF2ZSB0aXNzdWUgYXMgYSBmYWN0b3IKICAgIAogICAgZGRzIDwtIGVzdGltYXRlU2l6ZUZhY3RvcnMoZGRzX21hdCkKICAgIAogICAgZGRzX21hdCRkZXNpZ24gIyBQcmludCB0aGUgZGVzaWduIG9mIHRoZSBleHBlcmltZW50CiAgICBkZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNfbWF0KQogICAgCiAgICBudW1fc2FtcGxlc19tZWV0aW5nX2NyaXRlcmlhIDwtIDYgIyBiZSBzdHJpY3QgYW5kIGVuZm9yY2UgdGhhdCBhdCBsZWFzdCBoYWxmIHRoZSBzYW1wbGVzIG5lZWQgdG8gbWVldCB0aGUgY3JpdGVyaWEgKGkuZS4gb25lIGZ1bGwgY29uZGl0aW9uKQogICAgbnVtX2NvdW50c19pbl9nZW5lIDwtIDEwICAjIFRoZXkgbmVlZCBhdCBsZWFzdCAxMCBjb3VudHMKICAgIGtlZXAgPC0gcm93U3Vtcyhjb3VudHMoZGRzX21hdCkgPj0gbnVtX2NvdW50c19pbl9nZW5lKSA+PSBudW1fc2FtcGxlc19tZWV0aW5nX2NyaXRlcmlhCiAgICBkZHMgPC0gZGRzX21hdFtrZWVwLF0gIyBPbmx5IGtlZXAgdGhlIHJvd3Mgd2l0aCB0aGlzIGNyaXRlcmlhCiAgICAKICAgICMgTGV0J3MgcHJpbnQgdGhlIG51bWJlciBvZiByb3dzICYgY29sdW1uCiAgICBwcmludChwYXN0ZSgiRGF0YXNldCBkaW1lbnNpb25zOiAiLCBucm93KGRkcyksIG5jb2woZGRzKSkpCiAgICBpZiAobmNvbChkZHMpICE9IDEyKSB7CiAgICAgIHByaW50KHBhc3RlKCI9PT09PT09PT09PT09PT09PT0gV0FSTklORyBXQVJOSU5HIFdBUk5JTkcgWU9VUiBDT0xVTU5TIE1BWSBIQVZFIFRIRSBXUk9ORyBESU1TICA9PT09PT09PT09PT09PT09PT09PT09PT09PT0iLCBzZXA9IiIpKQogICAgfQogICAgCiAgICAjIFJ1biBERXNlcTIKICAgIGRkcyA8LSBERVNlcShkZHMpCiAgICAKICAgICMgQnVpbGQgcmVzdWx0cyB0YWJsZQogICAgcmVzIDwtIHJlc3VsdHMoZGRzKQogICAgcHJpbnQocGFzdGUoIkRlc2VxMiBkZXNpZ246ICIsIGRlc2lnbihkZHMpKSkKCiAgICAjIFN1bWFyaXNlIHRoZSByZXN1bHRzCiAgICBzdW1tYXJ5KHJlcykKICAgIAogICAgIyBMYXN0bHksIHdlIG1heSB3YW50IHRvIHNlZSB0aGUgcmVzdWx0cyBvZiB0aGUgaGlnaCBsb2dmb2xkY2hhbmdlIGUuZy4gPiAxIHdpdGggYSBwYWRqIHZhbHVlIDwgMC4wNQogICAgcmVzX3BhZGowNV9sZmMxIDwtIHJlc3VsdHMoZGRzLCBsZmNUaHJlc2hvbGQ9MikKICAgIHRhYmxlKHJlc19wYWRqMDVfbGZjMSRwYWRqIDwgMC4wNSkKICAgIAogICAgIyBTYXZlIHRoZSByZXN1bHRzCiAgICByZXNfb3JkZXJlZCA8LSByZXNbb3JkZXIocmVzJHB2YWx1ZSksXQogICAgb3V0cHV0X2ZpbGVuYW1lIDwtIHBhc3RlKHByb2plY3RfZGlyLCBvdXRwdXRfZmlsZW5hbWUsIHNlcD0nJykKICAgIHdyaXRlLmNzdihyZXNfb3JkZXJlZCwgZmlsZSA9IG91dHB1dF9maWxlbmFtZSkKICAgIHJldHVybihyZXNfb3JkZXJlZCkKfQoKYGBgCgojIyBSdW4gREUgb24gZWFjaCB0aXNzdWUKCkhlcmUgd2UgcnVuIHRoZSBERSBhbmFseXNpcyBvbiBlYWNoIHRpc3N1ZSBmb3IgdGhlIGNvbXBhcmlzb24uCmBgYHtyfQoKcnVuRGVzZXEyQmV0d2VlbkNvbmQocGFzdGUoJ21lcmdlZF9kZl9mYl9GRUFUVVJFX0NPVU5UU18nLCBkYXRlLCAnLmNzdicsIHNlcD0nJyksIHBhc3RlKCdERXNlcTJfQ05TX2ZiXycsIGRhdGUsICcuY3N2Jywgc2VwPScnKSkKcnVuRGVzZXEyQmV0d2VlbkNvbmQocGFzdGUoJ21lcmdlZF9kZl9tYl9GRUFUVVJFX0NPVU5UU18nLCBkYXRlLCAnLmNzdicsIHNlcD0nJyksIHBhc3RlKCdERXNlcTJfQ05TX21iXycsIGRhdGUsICcuY3N2Jywgc2VwPScnKSkKcnVuRGVzZXEyQmV0d2VlbkNvbmQocGFzdGUoJ21lcmdlZF9kZl9oYl9GRUFUVVJFX0NPVU5UU18nLCBkYXRlLCAnLmNzdicsIHNlcD0nJyksIHBhc3RlKCdERXNlcTJfQ05TX2hiXycsIGRhdGUsICcuY3N2Jywgc2VwPScnKSkKcnVuRGVzZXEyQmV0d2VlbkNvbmQocGFzdGUoJ21lcmdlZF9kZl9zY19GRUFUVVJFX0NPVU5UU18nLCBkYXRlLCAnLmNzdicsIHNlcD0nJyksIHBhc3RlKCdERXNlcTJfQ05TX3NjXycsIGRhdGUsICcuY3N2Jywgc2VwPScnKSkKCmBgYAoKIyMgTm9ybWFsaXNlIHRoZSBkYXRhCmBgYHtyfQpsaWJyYXJ5KGVkZ2VSKQoKZmlsZW5hbWUgPC0gcGFzdGUocHJvamVjdF9kaXIsICdtZXJnZWRfZGZfRkVBVFVSRV9DT1VOVFNfJywgZGF0ZSwgJy5jc3YnLCBzZXA9JycpCiMgaHR0cHM6Ly9iaW9jb25kdWN0b3Iub3JnL3BhY2thZ2VzL3JlbGVhc2Uvd29ya2Zsb3dzL3ZpZ25ldHRlcy9ybmFzZXFHZW5lL2luc3QvZG9jL3JuYXNlcUdlbmUuaHRtbApjb3VudHMgPC0gcmVhZC5jc3YoZmlsZW5hbWUsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICIsIikKcm93bmFtZXMoY291bnRzKSA8LSBjb3VudHMkZW50cmV6Z2VuZV9pZApnZW5lcyA8LSBjb3VudHMkZW50cmV6Z2VuZV9pZAoKIyBMZXQncyBtYWtlIHN1cmUgb3VyIGNvdW50IGRhdGEgaXMgaW4gbWF0cml4IGZvcm1hdCBhbmQgaXMgb25seSB0aGUgbnVtZXJpYyBjb2x1bW5zIGkuZS4gZXZlcnl0aGluZyBidXQgdGhlIGdlbmVzCmNvdW50cyA8LSBjb3VudHNbLDI6bmNvbChjb3VudHMpXQpjb3VudHNbaXMubmEoY291bnRzKV0gPSAwCiMgSGVyZSB3ZSBnZXQgdGhlIG5hbWVzIG9mIHRoZSBjb2x1bW5zLCBmb3IgbXkgc3R1ZmYgSSBhbHdheXMgaGF2ZSBhbGwgdGhlIGluZm8gaW4gb25lIHN0cmluZyBhcyBJIGZpbmQgaXQgbWFrZXMgaXQgZWFzaWVyCiMgdGhpcyBtZWFucyBlYWNoIG9mIHRoZSAiZ3JvdXBzIiBhcmUgc2VwYXJhdGVkIGJ5IGEgIl8iIHRoaXMgbWF5IGJlIGRpZmZlcmVudCBmb3IgeW91CnNhbXBsZU5hbWVzIDwtIGNvbG5hbWVzKGNvdW50cykgIyBTYW1wbGUgbmFtZXMKCiMgRm9yIERFc2VxMiB3ZSBuZWVkIHRvIHR1cm4gdGhpcyBpbnRvIGEgZGF0YWZyYW1lIApzYW1wbGVERiA9IGRhdGEuZnJhbWUoc2FtcGxlTmFtZXMgPSBzYW1wbGVOYW1lcykKCiMgTWFrZSBzdXJlIHdlIGRvbid0IGluY2x1ZGUgdGhlIElEIGluIG91ciBjb2x1bW5zCmNvdW50TWF0cml4IDwtIGFzLm1hdHJpeChjb3VudHMpCgojIFdlIG5vdyBzZXQgdGhlIHJvdyBuYW1lcyB0byBiZSB0aGUgZ2VuZSBJRHMKcm93bmFtZXMoY291bnRNYXRyaXgpIDwtIGdlbmVzCgpkZHNNYXQgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSBjb3VudE1hdHJpeCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IHNhbXBsZURGLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ24gPSB+IDEpCgpkZHMgPC0gZXN0aW1hdGVTaXplRmFjdG9ycyhkZHNNYXQpCm91dHB1dEZpbGVuYW1lIDwtIHBhc3RlKHByb2plY3RfZGlyLCAnbWVyZ2VkX2RmX0ZFQVRVUkVfQ09VTlRTX0RFc2VxMk5vcm1fJywgZGF0ZSwgJy5jc3YnLCBzZXA9JycpCndyaXRlLmNzdihjb3VudHMoZGRzLG5vcm1hbGl6ZWQ9VFJVRSksIGZpbGUgPSBvdXRwdXRGaWxlbmFtZSkKCnJsZCA8LSBybG9nKGNvdW50TWF0cml4ICsgMSwgYmxpbmQgPSBGQUxTRSkKcm93bmFtZXMocmxkKSA8LSBnZW5lcwpvdXRwdXRGaWxlbmFtZSA8LSBwYXN0ZShwcm9qZWN0X2RpciwgJ21lcmdlZF9kZl9GRUFUVVJFX0NPVU5UU19ybG9nXycsIGRhdGUsICcuY3N2Jywgc2VwPScnKQp3cml0ZS5jc3YocmxkLCBmaWxlID0gb3V0cHV0RmlsZW5hbWUpCgojIEJhc2VkIG9uIHRoZSBkb2N1bWVudGF0aW9uIGJlbG93LCBpdCBpcyBiZXN0IHRvIHVzZSBUTU0gbm9ybWFsaXNhdGlvbiBmcm9tIEVkZ2VSIHdoZW4gCiMgY29tcGFyaW5nIGFjY3Jvc3MgZ2VuZXMsIHdoaWNoIGlzIHdoYXQgd2Ugd2lsbCBiZSBkb2luZyBpbiBvdXIgc3Vic2VxdWVudCBhbmFseXNlcy4KIyBodHRwczovL2hiY3RyYWluaW5nLmdpdGh1Yi5pby9ER0Vfd29ya3Nob3AvbGVzc29ucy8wMl9ER0VfY291bnRfbm9ybWFsaXphdGlvbi5odG1sCiMgaHR0cHM6Ly9yZHJyLmlvL2Jpb2MvZWRnZVIvbWFuL2NhbGNOb3JtRmFjdG9ycy5odG1sCiMgaHR0cHM6Ly93d3cuYmlvY29uZHVjdG9yLm9yZy9wYWNrYWdlcy9yZWxlYXNlL2Jpb2MvdmlnbmV0dGVzL2VkZ2VSL2luc3QvZG9jL2VkZ2VSVXNlcnNHdWlkZS5wZGYKIyBodHRwczovL3d3dy5iaW9zdGFycy5vcmcvcC8zMTc3MDEvCgpkZ2UgPC0gREdFTGlzdChjb3VudHM9Y291bnRNYXRyaXgpCmNwbShkZ2UpCmRnZSA8LSBjYWxjTm9ybUZhY3RvcnMoZGdlLCBtZXRob2Q9IlRNTSIpCnRtbSA8LSBjcG0oZGdlKQpyb3duYW1lcyh0bW0pIDwtIGdlbmVzCgpvdXRwdXRGaWxlbmFtZSA8LSBwYXN0ZShwcm9qZWN0X2RpciwgJ21lcmdlZF9kZl9GRUFUVVJFX0NPVU5UU190bW1fJywgZGF0ZSwgJy5jc3YnLCBzZXA9JycpCndyaXRlLmNzdih0bW0sIGZpbGUgPSBvdXRwdXRGaWxlbmFtZSwgcm93Lm5hbWVzPVRSVUUpCgp2c2QgPC0gdnN0KGRkcywgYmxpbmQgPSBUUlVFKQpyb3duYW1lcyh2c2QpIDwtIGdlbmVzCm91dHB1dEZpbGVuYW1lIDwtIHBhc3RlKHByb2plY3RfZGlyLCAnbWVyZ2VkX2RmX0ZFQVRVUkVfQ09VTlRTX3ZzdF8nLCBkYXRlLCAnLmNzdicsIHNlcD0nJykKd3JpdGUuY3N2KHJsZCwgZmlsZSA9IG91dHB1dEZpbGVuYW1lKQoKYGBgCgojIyMgUHJpbnQgc2Vzc2lvbiBpbmZvCmBgYHtyfQpzZXNzaW9uSW5mbygpCmBgYAoKIyMjIFJlZmVyZW5jZXM6CmhiY3RyYWluaW5nL0RHRV93b3Jrc2hvcC4gVGVhY2hpbmcgbWF0ZXJpYWxzIGF0IHRoZSBIYXJ2YXJkIENoYW4gQmlvaW5mb3JtYXRpY3MgQ29yZSwgMjAyMS4gQWNjZXNzZWQ6IEp1bi4gMTUsIDIwMjEuIFtPbmxpbmVdLiBBdmFpbGFibGU6IGh0dHBzOi8vZ2l0aHViLmNvbS9oYmN0cmFpbmluZy9ER0Vfd29ya3Nob3AgIAoKTG92ZSBNSSwgSHViZXIgVywgQW5kZXJzIFMgKDIwMTQpLiDigJxNb2RlcmF0ZWQgZXN0aW1hdGlvbiBvZiBmb2xkIGNoYW5nZSBhbmQgZGlzcGVyc2lvbiBmb3IgUk5BLXNlcSBkYXRhIHdpdGggREVTZXEyLuKAnSBHZW5vbWUgQmlvbG9neSwgMTUsIDU1MC4gZG9pOiAxMC4xMTg2L3MxMzA1OS0wMTQtMDU1MC04LiAgCgpNLiBELiBSb2JpbnNvbiwgRC4gSi4gTWNDYXJ0aHksIGFuZCBHLiBLLiBTbXl0aCwg4oCYZWRnZVI6IGEgQmlvY29uZHVjdG9yIHBhY2thZ2UgZm9yIGRpZmZlcmVudGlhbCBleHByZXNzaW9uIGFuYWx5c2lzIG9mIGRpZ2l0YWwgZ2VuZSBleHByZXNzaW9uIGRhdGHigJksIEJpb2luZm9ybWF0aWNzLCB2b2wuIDI2LCBuby4gMSwgcHAuIDEzOeKAkzE0MCwgSmFuLiAyMDEwLCBkb2k6IDEwLjEwOTMvYmlvaW5mb3JtYXRpY3MvYnRwNjE2LiAgCgo=