.libPaths("/n/data1/cores/ntc/R-4.0.1/library/")
setwd("/n/scratch3/groups/hms/cores/ntc/Weinstock008")
library(DESeq2)
working on master data file with scripts run (bedtools closest and
intersect) to link GGA annot genes to dREG filtered annot enhancers. add
in counts data from PRO and ATAC across dREG span.
full <- read.table("overall.bed", sep="\t")
colnames(full) <- c("chr_gene", "start_gene", "end_gene", "name_gene", "score_gene", "strand_gene",
"chr_peak", "start_peak", "end_peak", "name_peak", "score_peak", "strand_peak", "biotype", "distance")
write.table(full, "TCL_Gene_to_Enhancer_master.txt", quote = FALSE, sep = "\t", row.names = FALSE, col.names = TRUE)
load DEseq and normalize with DEseq size factors based on depth
Import gene body counts table generated in O2 into R
normalizing counts for all data types with DEseq size factors and
melding to full table
raw_atac <- read.table("TCL_ATAC_counts.txt", header = TRUE, sep = "\t", row.names = 1)
raw_pro <- read.table("TCL_PRO_counts.txt", header = TRUE, sep = "\t", row.names = 1)
raw_rna <- read.table("TCL_RNA_counts.txt", header = TRUE, sep = "\t", row.names = 1)
Now PRO
### Create metadata object to categorize samples:
metadata_pro <- data.frame(row.names = colnames(raw_pro[, 6:ncol(raw_pro)]),
cell_line = c(rep("TCL_A",12),rep("TCL_B",12)))
metadata_pro # verify the table looks ok
#confirm that row and column names match
all(rownames(metadata_pro) %in% colnames(raw_pro))
all(rownames(metadata_pro) == colnames(raw_pro)[6:ncol(raw_pro)])
## Create DESeq Data Set from the count table, and sample list:
dds_pro <- DESeqDataSetFromMatrix(countData = raw_pro[, 6:ncol(raw_pro)], # the matrix of counts from featureCounts;
colData = metadata_pro, # the sample table created in the last step;
design= ~cell_line) # this is R's notation for models
dds_pro <- estimateSizeFactors(dds_pro)
deseq_sizes_pro <- as.data.frame(sizeFactors(dds_pro))
deseq_sizes_pro
write.table(deseq_sizes_pro, "PRO_norm_factors.txt", quote = FALSE, sep = "\t", row.names = TRUE, col.names = TRUE)
#normalization of PRO data
dds_pro <- estimateDispersions(dds_pro)
pdf("Dispersion_PRO_norm.pdf")
plotDispEsts(dds_pro)
dev.off()
# check results of normalization
colSums(counts(dds_pro)) # raw read counts per sample
colSums(counts(dds_pro, normalized=T)) # Total number of normalized counts per sample
data.frame(colSums(counts(dds_pro)), (colSums(counts(dds_pro, normalized=T))), row.names=colnames(counts(dds_pro)))
write.table(counts(dds_pro, normalized=TRUE), file="PRO_norm_counts.txt", sep="\t")
counts_pro <- read.table("PRO_norm_counts.txt", sep="\t")
counts_pro$dREG <- row.names(counts_pro)
full <- merge(full, counts_pro, by.x = "name_peak", by.y = "dREG", all.x=TRUE)
Now RNA
### Create metadata object to categorize samples:
metadata_rna <- data.frame(row.names = colnames(raw_rna[, 6:ncol(raw_rna)]),
cell_line = c(rep("TCL_A",12),rep("TCL_B",12)))
metadata_rna # verify the table looks ok
#confirm that row and column names match
all(rownames(metadata_rna) %in% colnames(raw_rna))
all(rownames(metadata_rna) == colnames(raw_rna)[6:ncol(raw_rna)])
## Create DESeq Data Set from the count table, and sample list:
dds_rna <- DESeqDataSetFromMatrix(countData = raw_rna[, 6:ncol(raw_rna)], # the matrix of counts from featureCounts;
colData = metadata_rna, # the sample table created in the last step;
design= ~cell_line) # this is R's notation for models
dds_rna <- estimateSizeFactors(dds_rna)
deseq_sizes_rna <- as.data.frame(sizeFactors(dds_rna))
deseq_sizes_rna
write.table(deseq_sizes_rna, "RNA_norm_factors.txt", quote = FALSE, sep = "\t", row.names = TRUE, col.names = TRUE)
#normalization of RNA data
dds_rna <- estimateDispersions(dds_rna)
pdf("Dispersion_RNA_norm.pdf")
plotDispEsts(dds_rna)
dev.off()
# check results of normalization
colSums(counts(dds_rna)) # raw read counts per sample
colSums(counts(dds_rna, normalized=T)) # Total number of normalized counts per sample
data.frame(colSums(counts(dds_rna)), (colSums(counts(dds_rna, normalized=T))), row.names=colnames(counts(dds_rna)))
write.table(counts(dds_rna, normalized=TRUE), file="RNA_norm_counts.txt", sep="\t")
counts_rna <- read.table("RNA_norm_counts.txt", sep="\t")
counts_rna$dREG <- row.names(counts_rna)
full <- merge(full, counts_rna, by.x = "name_peak", by.y = "dREG", all.x=TRUE)
final table completed
write.table(full, "TCL_Final_gene_to_enhancer.txt", quote = FALSE, sep = "\t", row.names = FALSE, col.names = TRUE)
# clean-up and save out DEseq data sets
saveRDS(dds_atac, file="ATAC.rds")
saveRDS(dds_pro, file="PRO.rds")
saveRDS(dds_rna, file="RNA.rds")
######### END #########
## MKJ 24JUL24
LS0tCnRpdGxlOiAiQ29tYmluZWQgVCBDZWxsIEx5bXBob21hIENlbGwgTGluZSBBbmFseXNpcyBvZiBSTkEtc2VxLCBQUk8tc2VxLCBhbmQgQVRBQy1zZXEiCm91dHB1dDogaHRtbF9ub3RlYm9vawplZGl0b3Jfb3B0aW9uczogCmNodW5rX291dHB1dF90eXBlOiBpbmxpbmUKLS0tCgpgYGB7cn0KLmxpYlBhdGhzKCIvbi9kYXRhMS9jb3Jlcy9udGMvUi00LjAuMS9saWJyYXJ5LyIpCnNldHdkKCIvbi9zY3JhdGNoMy9ncm91cHMvaG1zL2NvcmVzL250Yy9XZWluc3RvY2swMDgiKQoKbGlicmFyeShERVNlcTIpCgpgYGAKCndvcmtpbmcgb24gbWFzdGVyIGRhdGEgZmlsZSB3aXRoIHNjcmlwdHMgcnVuIChiZWR0b29scyBjbG9zZXN0IGFuZCBpbnRlcnNlY3QpIHRvIGxpbmsgR0dBIGFubm90IGdlbmVzIHRvIGRSRUcgZmlsdGVyZWQgYW5ub3QgZW5oYW5jZXJzLgphZGQgaW4gY291bnRzIGRhdGEgZnJvbSBQUk8gYW5kIEFUQUMgYWNyb3NzIGRSRUcgc3Bhbi4KCmBgYHtyfQpmdWxsIDwtIHJlYWQudGFibGUoIm92ZXJhbGwuYmVkIiwgc2VwPSJcdCIpCmNvbG5hbWVzKGZ1bGwpIDwtIGMoImNocl9nZW5lIiwgInN0YXJ0X2dlbmUiLCAiZW5kX2dlbmUiLCAibmFtZV9nZW5lIiwgInNjb3JlX2dlbmUiLCAic3RyYW5kX2dlbmUiLCAKICAgICAiY2hyX3BlYWsiLCAic3RhcnRfcGVhayIsICJlbmRfcGVhayIsICJuYW1lX3BlYWsiLCAic2NvcmVfcGVhayIsICJzdHJhbmRfcGVhayIsICJiaW90eXBlIiwgImRpc3RhbmNlIikKCndyaXRlLnRhYmxlKGZ1bGwsICJUQ0xfR2VuZV90b19FbmhhbmNlcl9tYXN0ZXIudHh0IiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IFRSVUUpCmBgYAoKbG9hZCBERXNlcSBhbmQgbm9ybWFsaXplIHdpdGggREVzZXEgc2l6ZSBmYWN0b3JzIGJhc2VkIG9uIGRlcHRoCkltcG9ydCBnZW5lIGJvZHkgY291bnRzIHRhYmxlIGdlbmVyYXRlZCBpbiBPMiBpbnRvIFIKCm5vcm1hbGl6aW5nIGNvdW50cyBmb3IgYWxsIGRhdGEgdHlwZXMgd2l0aCBERXNlcSBzaXplIGZhY3RvcnMgYW5kIG1lbGRpbmcgdG8gZnVsbCB0YWJsZQoKYGBge3J9CnJhd19hdGFjIDwtIHJlYWQudGFibGUoIlRDTF9BVEFDX2NvdW50cy50eHQiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSAxKQpyYXdfcHJvIDwtIHJlYWQudGFibGUoIlRDTF9QUk9fY291bnRzLnR4dCIsIGhlYWRlciA9IFRSVUUsIHNlcCA9ICJcdCIsIHJvdy5uYW1lcyA9IDEpCnJhd19ybmEgPC0gcmVhZC50YWJsZSgiVENMX1JOQV9jb3VudHMudHh0IiwgaGVhZGVyID0gVFJVRSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gMSkKCmBgYAoKIyBBVEFDIGZpcnN0ICMjIyMjCiMjIyBDcmVhdGUgbWV0YWRhdGEgb2JqZWN0IHRvIGNhdGVnb3JpemUgc2FtcGxlczoKCmBgYHtyfQptZXRhZGF0YV9hdGFjIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzID0gY29sbmFtZXMocmF3X2F0YWNbLCA2Om5jb2wocmF3X2F0YWMpXSksCiAgICAgICAgICAgICAgICAgICAgICAgY2VsbF9saW5lID0gYyhyZXAoIlRDTCIsMjMpLHJlcCgiT3RoZXIiLDEpKSkKICAgICAgICAgICAgICAgICAgICAgICAKbWV0YWRhdGFfYXRhYyAjIHZlcmlmeSB0aGUgdGFibGUgbG9va3Mgb2sKCiNjb25maXJtIHRoYXQgcm93IGFuZCBjb2x1bW4gbmFtZXMgbWF0Y2gKYWxsKHJvd25hbWVzKG1ldGFkYXRhX2F0YWMpICVpbiUgY29sbmFtZXMocmF3X2F0YWMpKQphbGwocm93bmFtZXMobWV0YWRhdGFfYXRhYykgPT0gY29sbmFtZXMocmF3X2F0YWMpWzY6bmNvbChyYXdfYXRhYyldKQoKCiMjIENyZWF0ZSBERVNlcSBEYXRhIFNldCBmcm9tIHRoZSBjb3VudCB0YWJsZSwgYW5kIHNhbXBsZSBsaXN0OgoKZGRzX2F0YWMgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSByYXdfYXRhY1ssIDY6bmNvbChyYXdfYXRhYyldLCAgICAgICMgdGhlIG1hdHJpeCBvZiBjb3VudHMgZnJvbSBmZWF0dXJlQ291bnRzOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGFfYXRhYywgICAgICAgICAgICAgICAgICAgICAjIHRoZSBzYW1wbGUgdGFibGUgY3JlYXRlZCBpbiB0aGUgbGFzdCBzdGVwOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXNpZ249IH5jZWxsX2xpbmUpICAgICAgICAgICAgIyB0aGlzIGlzIFIncyBub3RhdGlvbiBmb3IgbW9kZWxzCgpkZHNfYXRhYyA8LSBlc3RpbWF0ZVNpemVGYWN0b3JzKGRkc19hdGFjKQpkZXNlcV9zaXplc19hdGFjIDwtIGFzLmRhdGEuZnJhbWUoc2l6ZUZhY3RvcnMoZGRzX2F0YWMpKQpkZXNlcV9zaXplc19hdGFjCndyaXRlLnRhYmxlKGRlc2VxX3NpemVzX2F0YWMsICJBVEFDX25vcm1fZmFjdG9ycy50eHQiLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBUUlVFKQoKIyBub3JtYWxpemF0aW9uIG9mIEFUQUMgZGF0YQoKZGRzX2F0YWMgPC0gZXN0aW1hdGVEaXNwZXJzaW9ucyhkZHNfYXRhYykKcGRmKCJEaXNwZXJzaW9uX0FUQUNfbm9ybS5wZGYiKQpwbG90RGlzcEVzdHMoZGRzX2F0YWMpCmRldi5vZmYoKQoKIyBjaGVjayByZXN1bHRzIG9mIG5vcm1hbGl6YXRpb24KY29sU3Vtcyhjb3VudHMoZGRzX2F0YWMpKSAgICAgICAgICAgICAgICAjIHJhdyByZWFkIGNvdW50cyBwZXIgc2FtcGxlCmNvbFN1bXMoY291bnRzKGRkc19hdGFjLCBub3JtYWxpemVkPVQpKSAgIyBUb3RhbCBudW1iZXIgb2Ygbm9ybWFsaXplZCBjb3VudHMgcGVyIHNhbXBsZQpkYXRhLmZyYW1lKGNvbFN1bXMoY291bnRzKGRkc19hdGFjKSksIChjb2xTdW1zKGNvdW50cyhkZHNfYXRhYywgbm9ybWFsaXplZD1UKSkpLCByb3cubmFtZXM9Y29sbmFtZXMoY291bnRzKGRkc19hdGFjKSkpCgp3cml0ZS50YWJsZShjb3VudHMoZGRzX2F0YWMsIG5vcm1hbGl6ZWQ9VFJVRSksIGZpbGU9IkFUQUNfbm9ybV9jb3VudHMudHh0Iiwgc2VwPSJcdCIpCmNvdW50c19hdGFjIDwtIHJlYWQudGFibGUoIkFUQUNfbm9ybV9jb3VudHMudHh0Iiwgc2VwPSJcdCIpCmNvdW50c19hdGFjJGRSRUcgPC0gcm93Lm5hbWVzKGNvdW50c19hdGFjKQoKZnVsbCA8LSBtZXJnZShmdWxsLCBjb3VudHNfYXRhYywgYnkueCA9ICJuYW1lX3BlYWsiLCBieS55ID0gImRSRUciLCBhbGwueD1UUlVFKQoKYGBgCgojIE5vdyBQUk8gIyMjIyMjIyMjIyMjIyMjCgpgYGB7cn0KIyMjIENyZWF0ZSBtZXRhZGF0YSBvYmplY3QgdG8gY2F0ZWdvcml6ZSBzYW1wbGVzOgoKbWV0YWRhdGFfcHJvIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzID0gY29sbmFtZXMocmF3X3Byb1ssIDY6bmNvbChyYXdfcHJvKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbF9saW5lID0gYyhyZXAoIlRDTF9BIiwxMikscmVwKCJUQ0xfQiIsMTIpKSkKCm1ldGFkYXRhX3BybyAjIHZlcmlmeSB0aGUgdGFibGUgbG9va3Mgb2sKCiNjb25maXJtIHRoYXQgcm93IGFuZCBjb2x1bW4gbmFtZXMgbWF0Y2gKYWxsKHJvd25hbWVzKG1ldGFkYXRhX3BybykgJWluJSBjb2xuYW1lcyhyYXdfcHJvKSkKYWxsKHJvd25hbWVzKG1ldGFkYXRhX3BybykgPT0gY29sbmFtZXMocmF3X3BybylbNjpuY29sKHJhd19wcm8pXSkKCgojIyBDcmVhdGUgREVTZXEgRGF0YSBTZXQgZnJvbSB0aGUgY291bnQgdGFibGUsIGFuZCBzYW1wbGUgbGlzdDoKCmRkc19wcm8gPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSByYXdfcHJvWywgNjpuY29sKHJhd19wcm8pXSwgICAgICAjIHRoZSBtYXRyaXggb2YgY291bnRzIGZyb20gZmVhdHVyZUNvdW50czsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGFfcHJvLCAgICAgICAgICAgICAgICAgICAgICMgdGhlIHNhbXBsZSB0YWJsZSBjcmVhdGVkIGluIHRoZSBsYXN0IHN0ZXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduPSB+Y2VsbF9saW5lKSAgICAgICAgICAgICMgdGhpcyBpcyBSJ3Mgbm90YXRpb24gZm9yIG1vZGVscwoKZGRzX3BybyA8LSBlc3RpbWF0ZVNpemVGYWN0b3JzKGRkc19wcm8pCmRlc2VxX3NpemVzX3BybyA8LSBhcy5kYXRhLmZyYW1lKHNpemVGYWN0b3JzKGRkc19wcm8pKQpkZXNlcV9zaXplc19wcm8Kd3JpdGUudGFibGUoZGVzZXFfc2l6ZXNfcHJvLCAiUFJPX25vcm1fZmFjdG9ycy50eHQiLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBUUlVFKQoKI25vcm1hbGl6YXRpb24gb2YgUFJPIGRhdGEKCmRkc19wcm8gPC0gZXN0aW1hdGVEaXNwZXJzaW9ucyhkZHNfcHJvKQpwZGYoIkRpc3BlcnNpb25fUFJPX25vcm0ucGRmIikKcGxvdERpc3BFc3RzKGRkc19wcm8pCmRldi5vZmYoKQoKIyBjaGVjayByZXN1bHRzIG9mIG5vcm1hbGl6YXRpb24KY29sU3Vtcyhjb3VudHMoZGRzX3BybykpICAgICAgICAgICAgICAgICMgcmF3IHJlYWQgY291bnRzIHBlciBzYW1wbGUKY29sU3Vtcyhjb3VudHMoZGRzX3Bybywgbm9ybWFsaXplZD1UKSkgICMgVG90YWwgbnVtYmVyIG9mIG5vcm1hbGl6ZWQgY291bnRzIHBlciBzYW1wbGUKZGF0YS5mcmFtZShjb2xTdW1zKGNvdW50cyhkZHNfcHJvKSksIChjb2xTdW1zKGNvdW50cyhkZHNfcHJvLCBub3JtYWxpemVkPVQpKSksIHJvdy5uYW1lcz1jb2xuYW1lcyhjb3VudHMoZGRzX3BybykpKQoKd3JpdGUudGFibGUoY291bnRzKGRkc19wcm8sIG5vcm1hbGl6ZWQ9VFJVRSksIGZpbGU9IlBST19ub3JtX2NvdW50cy50eHQiLCBzZXA9Ilx0IikKY291bnRzX3BybyA8LSByZWFkLnRhYmxlKCJQUk9fbm9ybV9jb3VudHMudHh0Iiwgc2VwPSJcdCIpCmNvdW50c19wcm8kZFJFRyA8LSByb3cubmFtZXMoY291bnRzX3BybykKCgpmdWxsIDwtIG1lcmdlKGZ1bGwsIGNvdW50c19wcm8sIGJ5LnggPSAibmFtZV9wZWFrIiwgYnkueSA9ICJkUkVHIiwgYWxsLng9VFJVRSkKCmBgYAoKIyBOb3cgUk5BICMjIyMjIyMjIyMjCgpgYGB7cn0KIyMjIENyZWF0ZSBtZXRhZGF0YSBvYmplY3QgdG8gY2F0ZWdvcml6ZSBzYW1wbGVzOgoKbWV0YWRhdGFfcm5hIDwtIGRhdGEuZnJhbWUocm93Lm5hbWVzID0gY29sbmFtZXMocmF3X3JuYVssIDY6bmNvbChyYXdfcm5hKV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbF9saW5lID0gYyhyZXAoIlRDTF9BIiwxMikscmVwKCJUQ0xfQiIsMTIpKSkKCm1ldGFkYXRhX3JuYSAjIHZlcmlmeSB0aGUgdGFibGUgbG9va3Mgb2sKCiNjb25maXJtIHRoYXQgcm93IGFuZCBjb2x1bW4gbmFtZXMgbWF0Y2gKYWxsKHJvd25hbWVzKG1ldGFkYXRhX3JuYSkgJWluJSBjb2xuYW1lcyhyYXdfcm5hKSkKYWxsKHJvd25hbWVzKG1ldGFkYXRhX3JuYSkgPT0gY29sbmFtZXMocmF3X3JuYSlbNjpuY29sKHJhd19ybmEpXSkKCgojIyBDcmVhdGUgREVTZXEgRGF0YSBTZXQgZnJvbSB0aGUgY291bnQgdGFibGUsIGFuZCBzYW1wbGUgbGlzdDoKCmRkc19ybmEgPC0gREVTZXFEYXRhU2V0RnJvbU1hdHJpeChjb3VudERhdGEgPSByYXdfcm5hWywgNjpuY29sKHJhd19ybmEpXSwgICAgICAjIHRoZSBtYXRyaXggb2YgY291bnRzIGZyb20gZmVhdHVyZUNvdW50czsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2xEYXRhID0gbWV0YWRhdGFfcm5hLCAgICAgICAgICAgICAgICAgICAgICMgdGhlIHNhbXBsZSB0YWJsZSBjcmVhdGVkIGluIHRoZSBsYXN0IHN0ZXA7CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVzaWduPSB+Y2VsbF9saW5lKSAgICAgICAgICAgICMgdGhpcyBpcyBSJ3Mgbm90YXRpb24gZm9yIG1vZGVscwoKZGRzX3JuYSA8LSBlc3RpbWF0ZVNpemVGYWN0b3JzKGRkc19ybmEpCmRlc2VxX3NpemVzX3JuYSA8LSBhcy5kYXRhLmZyYW1lKHNpemVGYWN0b3JzKGRkc19ybmEpKQpkZXNlcV9zaXplc19ybmEKd3JpdGUudGFibGUoZGVzZXFfc2l6ZXNfcm5hLCAiUk5BX25vcm1fZmFjdG9ycy50eHQiLCBxdW90ZSA9IEZBTFNFLCBzZXAgPSAiXHQiLCByb3cubmFtZXMgPSBUUlVFLCBjb2wubmFtZXMgPSBUUlVFKQoKI25vcm1hbGl6YXRpb24gb2YgUk5BIGRhdGEKCmRkc19ybmEgPC0gZXN0aW1hdGVEaXNwZXJzaW9ucyhkZHNfcm5hKQpwZGYoIkRpc3BlcnNpb25fUk5BX25vcm0ucGRmIikKcGxvdERpc3BFc3RzKGRkc19ybmEpCmRldi5vZmYoKQoKIyBjaGVjayByZXN1bHRzIG9mIG5vcm1hbGl6YXRpb24KY29sU3Vtcyhjb3VudHMoZGRzX3JuYSkpICAgICAgICAgICAgICAgICMgcmF3IHJlYWQgY291bnRzIHBlciBzYW1wbGUKY29sU3Vtcyhjb3VudHMoZGRzX3JuYSwgbm9ybWFsaXplZD1UKSkgICMgVG90YWwgbnVtYmVyIG9mIG5vcm1hbGl6ZWQgY291bnRzIHBlciBzYW1wbGUKZGF0YS5mcmFtZShjb2xTdW1zKGNvdW50cyhkZHNfcm5hKSksIChjb2xTdW1zKGNvdW50cyhkZHNfcm5hLCBub3JtYWxpemVkPVQpKSksIHJvdy5uYW1lcz1jb2xuYW1lcyhjb3VudHMoZGRzX3JuYSkpKQoKd3JpdGUudGFibGUoY291bnRzKGRkc19ybmEsIG5vcm1hbGl6ZWQ9VFJVRSksIGZpbGU9IlJOQV9ub3JtX2NvdW50cy50eHQiLCBzZXA9Ilx0IikKY291bnRzX3JuYSA8LSByZWFkLnRhYmxlKCJSTkFfbm9ybV9jb3VudHMudHh0Iiwgc2VwPSJcdCIpCmNvdW50c19ybmEkZFJFRyA8LSByb3cubmFtZXMoY291bnRzX3JuYSkKCmZ1bGwgPC0gbWVyZ2UoZnVsbCwgY291bnRzX3JuYSwgYnkueCA9ICJuYW1lX3BlYWsiLCBieS55ID0gImRSRUciLCBhbGwueD1UUlVFKQoKYGBgCgpmaW5hbCB0YWJsZSBjb21wbGV0ZWQKCmBgYHtyfQp3cml0ZS50YWJsZShmdWxsLCAiVENMX0ZpbmFsX2dlbmVfdG9fZW5oYW5jZXIudHh0IiwgcXVvdGUgPSBGQUxTRSwgc2VwID0gIlx0Iiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IFRSVUUpCgojIGNsZWFuLXVwIGFuZCBzYXZlIG91dCBERXNlcSBkYXRhIHNldHMKCnNhdmVSRFMoZGRzX2F0YWMsIGZpbGU9IkFUQUMucmRzIikKc2F2ZVJEUyhkZHNfcHJvLCBmaWxlPSJQUk8ucmRzIikKc2F2ZVJEUyhkZHNfcm5hLCBmaWxlPSJSTkEucmRzIikKCiMjIyMjIyMjIyBFTkQgIyMjIyMjIyMjCiMjIE1LSiAyNEpVTDI0CmBgYAoKCg==