DESeq2
countmatrix <- read.delim("../output/kallisto_01.isoform.counts.matrix", header = TRUE, sep = '\t')
rownames(countmatrix) <- countmatrix$X
countmatrix <- countmatrix[,-1]
head(countmatrix)
countmatrix <- round(countmatrix, 0)
str(countmatrix)
dim(countmatrix)
dim(deseq2.colData)
deseq2.colData <- data.frame(condition=factor(c(rep("control", 12), rep("desicated", 12))),
type=factor(rep("single-read", 24)))
rownames(deseq2.colData) <- colnames(countmatrix)
deseq2.dds <- DESeqDataSetFromMatrix(countData = countmatrix,
colData = deseq2.colData,
design = ~ condition)
deseq2.dds <- DESeq(deseq2.dds)
deseq2.res <- results(deseq2.dds)
deseq2.res <- deseq2.res[order(rownames(deseq2.res)), ]
vsd <- vst(deseq2.dds, blind = FALSE)
plotPCA(vsd, intgroup = "condition")
# Select top 50 differentially expressed genes
res <- results(deseq2.dds)
res_ordered <- res[order(res$padj), ]
top_genes <- row.names(res_ordered)[1:50]
# Extract counts and normalize
counts <- counts(deseq2.dds, normalized = TRUE)
counts_top <- counts[top_genes, ]
# Log-transform counts
log_counts_top <- log2(counts_top + 1)
# Generate heatmap
pheatmap(log_counts_top, scale = "row")
# Count number of hits with adjusted p-value less then 0.05
dim(deseq2.res[!is.na(deseq2.res$padj) & deseq2.res$padj <= 0.05, ])
tmp <- deseq2.res
# The main plot
plot(tmp$baseMean, tmp$log2FoldChange, pch=20, cex=0.45, ylim=c(-3, 3), log="x", col="darkgray",
main="DEG Dessication (pval <= 0.05)",
xlab="mean of normalized counts",
ylab="Log2 Fold Change")
# Getting the significant points and plotting them again so they're a different color
tmp.sig <- deseq2.res[!is.na(deseq2.res$padj) & deseq2.res$padj <= 0.05, ]
points(tmp.sig$baseMean, tmp.sig$log2FoldChange, pch=20, cex=0.45, col="red")
# 2 FC lines
abline(h=c(-1,1), col="blue")
# Prepare the data for plotting
res_df <- as.data.frame(deseq2.res)
res_df$gene <- row.names(res_df)
# Create volcano plot
volcano_plot <- ggplot(res_df, aes(x = log2FoldChange, y = -log10(padj), color = padj < 0.05)) +
geom_point(alpha = 0.6, size = 1.5) +
scale_color_manual(values = c("grey", "red")) +
labs(title = "Volcano Plot",
x = "Log2 Fold Change",
y = "-Log10 Adjusted P-value",
color = "Significantly\nDifferentially Expressed") +
theme_minimal() +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
legend.position = "top")
print(volcano_plot)
write.table(tmp.sig, "../output/DEGlist.tab", sep = '\t', row.names = T)
deglist <- read.csv("../output/DEGlist.tab", sep = '\t', header = TRUE)
deglist$RowName <- rownames(deglist)
deglist2 <- deglist[, c("RowName", "pvalue")] # Optionally, reorder the columns
Annotation?
cg_sp <- read.csv("https://raw.githubusercontent.com/sr320/nb-2022/main/C_gigas/analyses/CgR-blastp-sp.tab", header = FALSE, sep="\t") %>%
distinct(V1, .keep_all = TRUE)
loc <- read.csv("https://raw.githubusercontent.com/sr320/nb-2022/main/C_gigas/analyses/LOC_Acc.tab", sep = " ", header = FALSE)
comb <- left_join(loc, cg_sp, by = c("V2" = "V1")) %>%
left_join(deglist, by = c("V1" = "RowName"))
Gene Enrichment
Analysis
gene_deg_status <- res_df %>%
mutate(degstaus = ifelse(padj < 0.05, 1, 0))
# Read the FASTA file
fasta_data <- readDNAStringSet("../data/rna.fna")
# Calculate gene lengths
gene_lengths <- width(fasta_data)
# Extract gene names/IDs from sequence IDs
gene_names <- sapply(names(fasta_data), function(x) strsplit(x, " ")[[1]][1])
# Create a data frame with gene IDs and lengths
gene_lengths_df <- data.frame(geneID = gene_names, length = gene_lengths)
Need GO Mappings
pwf <- nullp(gene_data, bias.data = gene_lengths)
GO_analysis <- goseq(pwf, gene2cat = "your_organism_GO_mapping")
LS0tCnRpdGxlOiAiUk5BLXNlcSIKYXV0aG9yOiBTdGV2ZW4gUm9iZXJ0cwpkYXRlOiAiYHIgZm9ybWF0KFN5cy50aW1lKCksICclZCAlQiwgJVknKWAiICAKb3V0cHV0OiAKICBodG1sX2RvY3VtZW50OgogICAgdGhlbWU6IHJlYWRhYmxlCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgY29kZV9kb3dubG9hZDogdHJ1ZQotLS0KYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoa25pdHIpCmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkoREVTZXEyKQpsaWJyYXJ5KHBoZWF0bWFwKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShkYXRhLnRhYmxlKQpsaWJyYXJ5KERUKQpsaWJyYXJ5KEJpb3N0cmluZ3MpCmtuaXRyOjpvcHRzX2NodW5rJHNldCgKICBlY2hvID0gVFJVRSwgICAgICAgICAjIERpc3BsYXkgY29kZSBjaHVua3MKICBldmFsID0gRkFMU0UsICAgICAgICAgIyBFdmFsdWF0ZSBjb2RlIGNodW5rcwogIHdhcm5pbmcgPSBGQUxTRSwgICAgICMgSGlkZSB3YXJuaW5ncwogIG1lc3NhZ2UgPSBGQUxTRSwgICAgICMgSGlkZSBtZXNzYWdlcwogIGZpZy53aWR0aCA9IDYsICAgICAgICMgU2V0IHBsb3Qgd2lkdGggaW4gaW5jaGVzCiAgZmlnLmhlaWdodCA9IDQsICAgICAgIyBTZXQgcGxvdCBoZWlnaHQgaW4gaW5jaGVzCiAgZmlnLmFsaWduID0gImNlbnRlciIgIyBBbGlnbiBwbG90cyB0byB0aGUgY2VudGVyCikKYGBgCiMgS2FsbGlzdG8gQWxpZ25tZW50CiMjIEdldHRpbmcgc2VxdWVuY2luZyByZWFkcwoKYGBge3IgcHVsbCwgZW5naW5lPSdiYXNoJ30KY2QgLi4vZGF0YSAKd2dldCAtLXJlY3Vyc2l2ZSAtLW5vLXBhcmVudCAtLW5vLWRpcmVjdG9yaWVzIFwKLS1hY2NlcHQgJyowMDEuZmFzdHEuZ3onIFwKaHR0cHM6Ly9nYW5uZXQuZmlzaC53YXNoaW5ndG9uLmVkdS9zZWFzaGVsbC9idS1naXRodWIvbmItMjAyMy9DZ2lnYXMvZGF0YS9ub3BwLwpgYGAKYGBge3IgZmFzdHFjLCBlbmdpbmU9J2Jhc2gnfQpjZCAuLi9kYXRhIAovaG9tZS9zaGFyZWQvRmFzdFFDL2Zhc3RxYyAqZmFzdHEuZ3ogLW8gLi4vb3V0cHV0CmBgYAoKYGBge2Jhc2h9CmV2YWwgIiQoL29wdC9hbmFjb25kYS9hbmFjb25kYTMvYmluL2NvbmRhIHNoZWxsLmJhc2ggaG9vaykiCmNvbmRhIGFjdGl2YXRlCndoaWNoIG11bHRpcWMKCmNkIC4uL291dHB1dAoKbXVsdGlxYyAuCmBgYAojIyBPYnRhaW4gdGhlIHJlZmVyZW5jZQpgYGB7ciBwdWxscmVmLCBlbmdpbmU9J2Jhc2gnfQpjZCAuLi9kYXRhCmN1cmwgLU8gaHR0cHM6Ly9nYW5uZXQuZmlzaC53YXNoaW5ndG9uLmVkdS9zZWFzaGVsbC9idS1naXRodWIvbmItMjAyMy9DZ2lnYXMvZGF0YS9ybmEuZm5hCmBgYAojIyBJbmRleCBSZWZlcmVuY2UKYGBge3Iga2FsbGlzdG8sIGVuZ2luZT0nYmFzaCd9CiMhL2Jpbi9iYXNoCgojIHJ1biBrYWxsaXN0byB0byBpbmRleCB0aGUgdHJhbnNjcmlwdG9tZQovaG9tZS9zaGFyZWQva2FsbGlzdG8va2FsbGlzdG8gXAoKIyBpbmRleCB0aGUgdHJhbnNjcmlwdG9tZQppbmRleCAtaSBcCgojIHNwZWNpZnkgdGhlIG91dHB1dCBmaWxlIG5hbWUKLi4vZGF0YS9jZ2lnYXNfcm9zbGluX3JuYS5pbmRleCBcCgojIHNwZWNpZnkgdGhlIGlucHV0IGZpbGUgbmFtZQouLi9kYXRhL3JuYS5mbmEKCmBgYAojIyBBbGlnbiByZWFkcwpgYGB7ciBrYWxsaXN0by1hbGlnbiwgZW5naW5lPSdiYXNoJ30KbWtkaXIgLi4vb3V0cHV0L2thbGxpc3RvXzAxCgpmaW5kIC4uL2RhdGEvKl9MMDAxX1IxXzAwMS5mYXN0cS5neiBcCnwgeGFyZ3MgYmFzZW5hbWUgLXMgX0wwMDFfUjFfMDAxLmZhc3RxLmd6IHwgeGFyZ3MgLUl7fSAvaG9tZS9zaGFyZWQva2FsbGlzdG8va2FsbGlzdG8gXApxdWFudCAtaSAuLi9kYXRhL2NnaWdhc19yb3NsaW5fcm5hLmluZGV4IFwKLW8gLi4vb3V0cHV0L2thbGxpc3RvXzAxL3t9IFwKLXQgNDAgXAotLXNpbmdsZSAtbCAxMDAgLXMgMTAgLi4vZGF0YS97fV9MMDAxX1IxXzAwMS5mYXN0cS5negpgYGAKIyMgTWVyZ2UgcXVhbnQgZGF0YQpgYGB7ciBtYXRyaXgsIGVuZ2luZT0nYmFzaCd9CnBlcmwgL2hvbWUvc2hhcmVkL3RyaW5pdHlybmFzZXEtdjIuMTIuMC91dGlsL2FidW5kYW5jZV9lc3RpbWF0ZXNfdG9fbWF0cml4LnBsIFwKLS1lc3RfbWV0aG9kIGthbGxpc3RvIFwKICAgIC0tZ2VuZV90cmFuc19tYXAgbm9uZSBcCiAgICAtLW91dF9wcmVmaXggLi4vb3V0cHV0L2thbGxpc3RvXzAxIFwKICAgIC0tbmFtZV9zYW1wbGVfYnlfYmFzZWRpciBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU0X1MxNDUvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU2X1MxMzYvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU4X1MxNDQvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTQ1X1MxNDAvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTQ4X1MxMzcvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTg5X1MxMzgvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU1X1MxNDYvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU3X1MxNDMvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvRDU5X1MxNDIvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTQ2X1MxNDEvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTQ5X1MxMzkvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTTkwX1MxNDcvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjQ4X1MxOTQvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjUwX1MxODcvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjUyX1MxODQvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU0X1MxOTMvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU2X1MxOTIvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU4X1MxOTUvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjQ5X1MxODUvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjUxX1MxODYvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjUzX1MxODgvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU1X1MxOTAvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU3X1MxOTEvYWJ1bmRhbmNlLnRzdiBcCiAgICAuLi9vdXRwdXQva2FsbGlzdG9fMDEvTjU5X1MxODkvYWJ1bmRhbmNlLnRzdgpgYGAKIyBERVNlcTIKYGBge3IsIGV2YWw9RkFMU0V9CmNvdW50bWF0cml4IDwtIHJlYWQuZGVsaW0oIi4uL291dHB1dC9rYWxsaXN0b18wMS5pc29mb3JtLmNvdW50cy5tYXRyaXgiLCBoZWFkZXIgPSBUUlVFLCBzZXAgPSAnXHQnKQpyb3duYW1lcyhjb3VudG1hdHJpeCkgPC0gY291bnRtYXRyaXgkWApjb3VudG1hdHJpeCA8LSBjb3VudG1hdHJpeFssLTFdCmhlYWQoY291bnRtYXRyaXgpCmBgYAoKYGBge3IsZXZhbD1GQUxTRX0KY291bnRtYXRyaXggPC0gcm91bmQoY291bnRtYXRyaXgsIDApCnN0cihjb3VudG1hdHJpeCkKYGBgCgoKYGBge3IsZXZhbD1GQUxTRX0KZGltKGNvdW50bWF0cml4KQpkaW0oZGVzZXEyLmNvbERhdGEpCmBgYApgYGB7cixldmFsPUZBTFNFfQpsZW5ndGgoY29sbmFtZXMoZGF0YSkpCmBgYAoKYGBge3IsIGV2YWw9RkFMU0V9CmRlc2VxMi5jb2xEYXRhIDwtIGRhdGEuZnJhbWUoY29uZGl0aW9uPWZhY3RvcihjKHJlcCgiY29udHJvbCIsIDEyKSwgcmVwKCJkZXNpY2F0ZWQiLCAxMikpKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZT1mYWN0b3IocmVwKCJzaW5nbGUtcmVhZCIsIDI0KSkpCnJvd25hbWVzKGRlc2VxMi5jb2xEYXRhKSA8LSBjb2xuYW1lcyhjb3VudG1hdHJpeCkKZGVzZXEyLmRkcyA8LSBERVNlcURhdGFTZXRGcm9tTWF0cml4KGNvdW50RGF0YSA9IGNvdW50bWF0cml4LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sRGF0YSA9IGRlc2VxMi5jb2xEYXRhLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlc2lnbiA9IH4gY29uZGl0aW9uKQpgYGAKYGBge3IsIGV2YWw9RkFMU0UsIGNhY2hlPUZBTFNFfQpkZXNlcTIuZGRzIDwtIERFU2VxKGRlc2VxMi5kZHMpCmRlc2VxMi5yZXMgPC0gcmVzdWx0cyhkZXNlcTIuZGRzKQpkZXNlcTIucmVzIDwtIGRlc2VxMi5yZXNbb3JkZXIocm93bmFtZXMoZGVzZXEyLnJlcykpLCBdCmBgYApgYGB7ciBQQ0EsIGV2YWw9RkFMU0V9CnZzZCA8LSB2c3QoZGVzZXEyLmRkcywgYmxpbmQgPSBGQUxTRSkKcGxvdFBDQSh2c2QsIGludGdyb3VwID0gImNvbmRpdGlvbiIpCmBgYAoKYGBge3IgaGVhdG1hcCwgZXZhbD1GQUxTRX0KIyBTZWxlY3QgdG9wIDUwIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcwpyZXMgPC0gcmVzdWx0cyhkZXNlcTIuZGRzKQpyZXNfb3JkZXJlZCA8LSByZXNbb3JkZXIocmVzJHBhZGopLCBdCnRvcF9nZW5lcyA8LSByb3cubmFtZXMocmVzX29yZGVyZWQpWzE6NTBdCgojIEV4dHJhY3QgY291bnRzIGFuZCBub3JtYWxpemUKY291bnRzIDwtIGNvdW50cyhkZXNlcTIuZGRzLCBub3JtYWxpemVkID0gVFJVRSkKY291bnRzX3RvcCA8LSBjb3VudHNbdG9wX2dlbmVzLCBdCgojIExvZy10cmFuc2Zvcm0gY291bnRzCmxvZ19jb3VudHNfdG9wIDwtIGxvZzIoY291bnRzX3RvcCArIDEpCgojIEdlbmVyYXRlIGhlYXRtYXAKcGhlYXRtYXAobG9nX2NvdW50c190b3AsIHNjYWxlID0gInJvdyIpCmBgYCAKYGBge3IsIGV2YWw9RkFMU0V9CmhlYWQoZGVzZXEyLnJlcykKYGBgCgoKCmBgYHtyLCBldmFsPUZBTFNFfQojIENvdW50IG51bWJlciBvZiBoaXRzIHdpdGggYWRqdXN0ZWQgcC12YWx1ZSBsZXNzIHRoZW4gMC4wNQpkaW0oZGVzZXEyLnJlc1shaXMubmEoZGVzZXEyLnJlcyRwYWRqKSAmIGRlc2VxMi5yZXMkcGFkaiA8PSAwLjA1LCBdKQpgYGAKYGBge3IsIGV2YWw9RkFMU0V9CnRtcCA8LSBkZXNlcTIucmVzCiMgVGhlIG1haW4gcGxvdApwbG90KHRtcCRiYXNlTWVhbiwgdG1wJGxvZzJGb2xkQ2hhbmdlLCBwY2g9MjAsIGNleD0wLjQ1LCB5bGltPWMoLTMsIDMpLCBsb2c9IngiLCBjb2w9ImRhcmtncmF5IiwKICAgICBtYWluPSJERUcgRGVzc2ljYXRpb24gIChwdmFsIDw9IDAuMDUpIiwKICAgICB4bGFiPSJtZWFuIG9mIG5vcm1hbGl6ZWQgY291bnRzIiwKICAgICB5bGFiPSJMb2cyIEZvbGQgQ2hhbmdlIikKIyBHZXR0aW5nIHRoZSBzaWduaWZpY2FudCBwb2ludHMgYW5kIHBsb3R0aW5nIHRoZW0gYWdhaW4gc28gdGhleSdyZSBhIGRpZmZlcmVudCBjb2xvcgp0bXAuc2lnIDwtIGRlc2VxMi5yZXNbIWlzLm5hKGRlc2VxMi5yZXMkcGFkaikgJiBkZXNlcTIucmVzJHBhZGogPD0gMC4wNSwgXQpwb2ludHModG1wLnNpZyRiYXNlTWVhbiwgdG1wLnNpZyRsb2cyRm9sZENoYW5nZSwgcGNoPTIwLCBjZXg9MC40NSwgY29sPSJyZWQiKQojIDIgRkMgbGluZXMKYWJsaW5lKGg9YygtMSwxKSwgY29sPSJibHVlIikKYGBgCmBgYHtyIG5ld3Bsb3QsIGV2YWw9RkFMU0V9CiMgUHJlcGFyZSB0aGUgZGF0YSBmb3IgcGxvdHRpbmcKcmVzX2RmIDwtIGFzLmRhdGEuZnJhbWUoZGVzZXEyLnJlcykKcmVzX2RmJGdlbmUgPC0gcm93Lm5hbWVzKHJlc19kZikKCiMgQ3JlYXRlIHZvbGNhbm8gcGxvdAp2b2xjYW5vX3Bsb3QgPC0gZ2dwbG90KHJlc19kZiwgYWVzKHggPSBsb2cyRm9sZENoYW5nZSwgeSA9IC1sb2cxMChwYWRqKSwgY29sb3IgPSBwYWRqIDwgMC4wNSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC42LCBzaXplID0gMS41KSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoImdyZXkiLCAicmVkIikpICsKICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdCIsCiAgICAgICB4ID0gIkxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC12YWx1ZSIsCiAgICAgICBjb2xvciA9ICJTaWduaWZpY2FudGx5XG5EaWZmZXJlbnRpYWxseSBFeHByZXNzZWQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIpCgpwcmludCh2b2xjYW5vX3Bsb3QpCmBgYApgYGB7ciwgZXZhbD1GQUxTRX0Kd3JpdGUudGFibGUodG1wLnNpZywgIi4uL291dHB1dC9ERUdsaXN0LnRhYiIsIHNlcCA9ICdcdCcsIHJvdy5uYW1lcyA9IFQpCmBgYAoKYGBge3IsIGV2YWw9RkFMU0V9CmRlZ2xpc3QgPC0gcmVhZC5jc3YoIi4uL291dHB1dC9ERUdsaXN0LnRhYiIsIHNlcCA9ICdcdCcsIGhlYWRlciA9IFRSVUUpCmRlZ2xpc3QkUm93TmFtZSA8LSByb3duYW1lcyhkZWdsaXN0KQpkZWdsaXN0MiA8LSBkZWdsaXN0WywgYygiUm93TmFtZSIsICJwdmFsdWUiKV0gIyBPcHRpb25hbGx5LCByZW9yZGVyIHRoZSBjb2x1bW5zCmBgYAoKCmBgYHtyLCBldmFsPUZBTFNFfQpkYXRhdGFibGUoZGVnbGlzdCkKYGBgCiMgQW5ub3RhdGlvbj8KYGBge3IsIGV2YWw9RkFMU0V9CmNnX3NwIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3IzMjAvbmItMjAyMi9tYWluL0NfZ2lnYXMvYW5hbHlzZXMvQ2dSLWJsYXN0cC1zcC50YWIiLCBoZWFkZXIgPSBGQUxTRSwgc2VwPSJcdCIpICAlPiUKICBkaXN0aW5jdChWMSwgLmtlZXBfYWxsID0gVFJVRSkKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0KbG9jIDwtIHJlYWQuY3N2KCJodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vc3IzMjAvbmItMjAyMi9tYWluL0NfZ2lnYXMvYW5hbHlzZXMvTE9DX0FjYy50YWIiLCBzZXAgPSAiICIsIGhlYWRlciA9IEZBTFNFKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFfQpjb21iIDwtIGxlZnRfam9pbihsb2MsIGNnX3NwLCBieSA9IGMoIlYyIiA9ICJWMSIpKSAlPiUKICBsZWZ0X2pvaW4oZGVnbGlzdCwgYnkgPSBjKCJWMSIgPSAiUm93TmFtZSIpKQpgYGAKCgojIEdlbmUgRW5yaWNobWVudCBBbmFseXNpcwpgYGB7ciwgZXZhbD1GQUxTRX0KZ2VuZV9kZWdfc3RhdHVzIDwtIHJlc19kZiAlPiUKICBtdXRhdGUoZGVnc3RhdXMgPSBpZmVsc2UocGFkaiA8IDAuMDUsIDEsIDApKSAKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0KIyBSZWFkIHRoZSBGQVNUQSBmaWxlCmZhc3RhX2RhdGEgPC0gcmVhZEROQVN0cmluZ1NldCgiLi4vZGF0YS9ybmEuZm5hIikKCiMgQ2FsY3VsYXRlIGdlbmUgbGVuZ3RocwpnZW5lX2xlbmd0aHMgPC0gd2lkdGgoZmFzdGFfZGF0YSkKCgojIEV4dHJhY3QgZ2VuZSBuYW1lcy9JRHMgZnJvbSBzZXF1ZW5jZSBJRHMKZ2VuZV9uYW1lcyA8LSBzYXBwbHkobmFtZXMoZmFzdGFfZGF0YSksIGZ1bmN0aW9uKHgpIHN0cnNwbGl0KHgsICIgIilbWzFdXVsxXSkKCiMgQ3JlYXRlIGEgZGF0YSBmcmFtZSB3aXRoIGdlbmUgSURzIGFuZCBsZW5ndGhzCmdlbmVfbGVuZ3Roc19kZiA8LSBkYXRhLmZyYW1lKGdlbmVJRCA9IGdlbmVfbmFtZXMsIGxlbmd0aCA9IGdlbmVfbGVuZ3RocykKCmBgYAoKIyMgIE5lZWQgR08gTWFwcGluZ3MKYGBge3IsIGV2YWw9RkFMU0V9CnB3ZiA8LSBudWxscChnZW5lX2RhdGEsIGJpYXMuZGF0YSA9IGdlbmVfbGVuZ3RocykKCkdPX2FuYWx5c2lzIDwtIGdvc2VxKHB3ZiwgZ2VuZTJjYXQgPSAieW91cl9vcmdhbmlzbV9HT19tYXBwaW5nIikKCmBgYAo=