1. load libraries
2. Load the filtered upregulated and Downregulated genes
3. Initial test
df <- df[!(df$Malignant.exp < 0.20 & df$Control.exp < 0.20), ]
df <- as.data.frame(df)
write.csv(df, "../18-03-25_top-markers/Psedibulk_Deseq2_filtered_on_mean.csv", row.names = FALSE)
# Ensure the dataframe has necessary columns: "gene", "avg_logFC", "p_val_adj"
# If gene names are stored as row names, move them to a column
if (!"gene" %in% colnames(df)) {
df <- rownames_to_column(df, "gene")
}
4. Initial test and visualization
library(dplyr)
library(ggplot2)
# Filter significant genes (p_val_adj < 0.05)
significant_genes <- df %>%
filter(p_val_adj < 1e-4)
# Select top 30 upregulated genes (highest avg_logFC)
top_30_up <- significant_genes %>%
arrange(desc(avg_logFC), p_val_adj) %>%
head(30)
# Filter out genes starting with "TRVB" and "TRAV" and select top 30 downregulated genes (lowest avg_logFC)
top_30_down <- significant_genes %>%
filter(!grepl("^TRBV", gene) & !grepl("^TRAV", gene)) %>% # Exclude genes starting with "TRVB" or "TRAV"
arrange(avg_logFC, p_val_adj) %>%
head(30)
# Combine both into one dataframe with a new column indicating direction
top_genes <- bind_rows(
top_30_up %>% mutate(direction = "Upregulated"),
top_30_down %>% mutate(direction = "Downregulated")
)
# Save both separately and combined
write.csv(top_30_up, "top_30_upregulated.csv", row.names = FALSE)
write.csv(top_30_down, "top_30_downregulated.csv", row.names = FALSE)
write.csv(top_genes, "top_30_biomarkers_combined.csv", row.names = FALSE)
# Print selected columns
print(top_genes %>% select(gene, avg_logFC, p_val_adj, Malignant.pct, Control.pct, Malignant.exp, Control.exp, direction))
# For the combined plot of upregulated and downregulated genes with custom colors
ggplot(top_genes, aes(x = reorder(gene, avg_logFC), y = avg_logFC, fill = avg_logFC > 0)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_manual(values = c("blue", "red")) + # Red for upregulated, Blue for downregulated
theme_minimal() +
labs(title = "Top 30 Upregulated and Downregulated Genes",
x = "Gene",
y = "Log2 Fold Change",
fill = "Expression")

# For separate plots for upregulated and downregulated genes
ggplot(top_30_up, aes(x = reorder(gene, avg_logFC), y = avg_logFC, fill = avg_logFC > 0)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_manual(values = c("red", "blue")) +
theme_minimal() +
labs(title = "Top 30 Upregulated Genes",
x = "Gene",
y = "Log2 Fold Change",
fill = "Expression")

ggplot(top_30_down, aes(x = reorder(gene, avg_logFC), y = avg_logFC, fill = avg_logFC < 0)) + # < 0 for downregulated genes
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_manual(values = c("blue", "red")) + # Red for upregulated, Blue for downregulated
theme_minimal() +
labs(title = "Top 30 Downregulated Genes",
x = "Gene",
y = "Log2 Fold Change",
fill = "Expression")

NA
NA
5. Volcano Plot
library(ggplot2)
library(ggrepel)
# Volcano plot with labeled top genes
volcano_plot <- ggplot(top_genes, aes(x = avg_logFC, y = -log10(p_val_adj))) +
geom_point(aes(color = avg_logFC), size = 3, alpha = 0.7) +
scale_color_gradient2(
low = "blue",
mid = "grey",
high = "red",
midpoint = median(top_genes$avg_logFC)
) +
geom_text_repel(
aes(label = gene), # Label genes
size = 3,
max.overlaps = 20 # Adjust to avoid label crowding
) +
theme_minimal() +
labs(
title = "Volcano Plot of Top 30 Biomarkers",
x = "log2 Fold Change (avg_logFC)",
y = "-log10(Adjusted p-value)",
color = "Fold Change"
)
print(volcano_plot)

6. Bar Plot of Top Genes by Fold Change
# Bar plot (sorted by fold change)
bar_plot <- ggplot(top_genes,
aes(x = reorder(gene, avg_logFC), y = avg_logFC,
fill = avg_logFC)) +
geom_col() +
scale_fill_gradient2(
low = "blue",
mid = "white",
high = "red",
midpoint = median(top_genes$avg_logFC)
) +
coord_flip() + # Horizontal bars
theme_minimal() +
labs(
title = "Top 30 Biomarkers by log2 Fold Change",
x = "Gene",
y = "avg_logFC"
)
print(bar_plot)

7. dotplot of Expression Prevalence
# Dot plot comparing pct.1 vs pct.2
dot_plot <- ggplot(top_genes, aes(x = Malignant.pct, y = Control.pct,
size = avg_logFC, color = avg_logFC)) +
geom_point(alpha = 0.8) +
geom_text_repel(aes(label = gene), size = 3, max.overlaps = 20) +
scale_color_gradient2(
low = "blue",
mid = "grey",
high = "red",
midpoint = median(top_genes$avg_logFC)
) +
theme_minimal() +
labs(
title = "Expression Prevalence: Target Group (pct.1) vs Control (pct.2)",
x = "Expression in Target Group (pct.1)",
y = "Expression in Control (pct.2)",
color = "Fold Change",
size = "Fold Change"
)
print(dot_plot)

8. dotplot of Mean Expression Prevalence
# Dot plot comparing pct.1 vs pct.2
dot_plot <- ggplot(top_genes, aes(x = Malignant.exp, y = Control.exp,
size = avg_logFC, color = avg_logFC)) +
geom_point(alpha = 0.8) +
geom_text_repel(aes(label = gene), size = 3, max.overlaps = 20) +
scale_color_gradient2(
low = "blue",
mid = "grey",
high = "red",
midpoint = median(top_genes$avg_logFC)
) +
theme_minimal() +
labs(
title = "Expression Prevalence: Target Group (exp.1) vs Control (exp.2)",
x = "Expression in Target Group (exp.1)",
y = "Expression in Control (exp.2)",
color = "Fold Change",
size = "Fold Change"
)
print(dot_plot)

9. FeaturePlot for Top30 UP
FeaturePlot(All_samples_Merged,
features = top_30_up$gene[1:10],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

FeaturePlot(All_samples_Merged,
features = top_30_up$gene[11:20],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

FeaturePlot(All_samples_Merged,
features = top_30_up$gene[21:30],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

NA
NA
10. FeaturePlot for Top30 DOWN
FeaturePlot(All_samples_Merged,
features = top_30_down$gene[1:10],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

FeaturePlot(All_samples_Merged,
features = top_30_down$gene[11:20],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

FeaturePlot(All_samples_Merged,
features = top_30_down$gene[21:30],
reduction = "umap",
cols = c("lightblue", "red"), # Custom color gradient from light blue to red
label = TRUE)

LS0tCnRpdGxlOiAiU2lnbmF0dXJlIE1hcmtlcnMoTWFsaWduYXRfdnNfTm9ybWFsX0NENFRjZWxscykgZmlsdGVyZWQgb24gTWVhbkV4cHJlc3Npb24iCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeSh0aWJibGUpICAjIEZvciBoYW5kbGluZyByb3cgbmFtZXMKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKYGBgCgoKIyAyLiBMb2FkIHRoZSBmaWx0ZXJlZCB1cHJlZ3VsYXRlZCBhbmQgRG93bnJlZ3VsYXRlZCBnZW5lcwpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEwfQoKIyBMb2FkIHRoZSBERSByZXN1bHRzIGZyb20gQ1NWCmRmIDwtIHJlYWQuY3N2KCIxLVBzZXVkb2J1bGtfREVzZXEyX0xSVF9ERV93aXRoX2xpYnJhLmNzdiIsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmBgYAoKCiMgMy4gIEluaXRpYWwgdGVzdApgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKZGYgPC0gZGZbIShkZiRNYWxpZ25hbnQuZXhwIDwgMC4yMCAmIGRmJENvbnRyb2wuZXhwIDwgMC4yMCksIF0KCmRmIDwtIGFzLmRhdGEuZnJhbWUoZGYpCgp3cml0ZS5jc3YoZGYsICIuLi8xOC0wMy0yNV90b3AtbWFya2Vycy9Qc2VkaWJ1bGtfRGVzZXEyX2ZpbHRlcmVkX29uX21lYW4uY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIEVuc3VyZSB0aGUgZGF0YWZyYW1lIGhhcyBuZWNlc3NhcnkgY29sdW1uczogImdlbmUiLCAiYXZnX2xvZ0ZDIiwgInBfdmFsX2FkaiIKIyBJZiBnZW5lIG5hbWVzIGFyZSBzdG9yZWQgYXMgcm93IG5hbWVzLCBtb3ZlIHRoZW0gdG8gYSBjb2x1bW4KaWYgKCEiZ2VuZSIgJWluJSBjb2xuYW1lcyhkZikpIHsKICBkZiA8LSByb3duYW1lc190b19jb2x1bW4oZGYsICJnZW5lIikKfQoKYGBgCgojIDQuICBJbml0aWFsIHRlc3QgYW5kIHZpc3VhbGl6YXRpb24KYGBge3IgLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgRmlsdGVyIHNpZ25pZmljYW50IGdlbmVzIChwX3ZhbF9hZGogPCAwLjA1KQpzaWduaWZpY2FudF9nZW5lcyA8LSBkZiAlPiUKICBmaWx0ZXIocF92YWxfYWRqIDwgMWUtNCkKCiMgU2VsZWN0IHRvcCAzMCB1cHJlZ3VsYXRlZCBnZW5lcyAoaGlnaGVzdCBhdmdfbG9nRkMpCnRvcF8zMF91cCA8LSBzaWduaWZpY2FudF9nZW5lcyAlPiUKICBhcnJhbmdlKGRlc2MoYXZnX2xvZ0ZDKSwgcF92YWxfYWRqKSAlPiUKICBoZWFkKDMwKQoKIyBGaWx0ZXIgb3V0IGdlbmVzIHN0YXJ0aW5nIHdpdGggIlRSVkIiIGFuZCAiVFJBViIgYW5kIHNlbGVjdCB0b3AgMzAgZG93bnJlZ3VsYXRlZCBnZW5lcyAobG93ZXN0IGF2Z19sb2dGQykKdG9wXzMwX2Rvd24gPC0gc2lnbmlmaWNhbnRfZ2VuZXMgJT4lCiAgZmlsdGVyKCFncmVwbCgiXlRSQlYiLCBnZW5lKSAmICFncmVwbCgiXlRSQVYiLCBnZW5lKSkgJT4lICAjIEV4Y2x1ZGUgZ2VuZXMgc3RhcnRpbmcgd2l0aCAiVFJWQiIgb3IgIlRSQVYiCiAgYXJyYW5nZShhdmdfbG9nRkMsIHBfdmFsX2FkaikgJT4lCiAgaGVhZCgzMCkKCiMgQ29tYmluZSBib3RoIGludG8gb25lIGRhdGFmcmFtZSB3aXRoIGEgbmV3IGNvbHVtbiBpbmRpY2F0aW5nIGRpcmVjdGlvbgp0b3BfZ2VuZXMgPC0gYmluZF9yb3dzKAogIHRvcF8zMF91cCAlPiUgbXV0YXRlKGRpcmVjdGlvbiA9ICJVcHJlZ3VsYXRlZCIpLAogIHRvcF8zMF9kb3duICU+JSBtdXRhdGUoZGlyZWN0aW9uID0gIkRvd25yZWd1bGF0ZWQiKQopCgojIFNhdmUgYm90aCBzZXBhcmF0ZWx5IGFuZCBjb21iaW5lZAp3cml0ZS5jc3YodG9wXzMwX3VwLCAidG9wXzMwX3VwcmVndWxhdGVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS5jc3YodG9wXzMwX2Rvd24sICJ0b3BfMzBfZG93bnJlZ3VsYXRlZC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KHRvcF9nZW5lcywgInRvcF8zMF9iaW9tYXJrZXJzX2NvbWJpbmVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyBQcmludCBzZWxlY3RlZCBjb2x1bW5zCnByaW50KHRvcF9nZW5lcyAlPiUgc2VsZWN0KGdlbmUsIGF2Z19sb2dGQywgcF92YWxfYWRqLCBNYWxpZ25hbnQucGN0LCBDb250cm9sLnBjdCwgTWFsaWduYW50LmV4cCwgQ29udHJvbC5leHAsIGRpcmVjdGlvbikpCgojIEZvciB0aGUgY29tYmluZWQgcGxvdCBvZiB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcyB3aXRoIGN1c3RvbSBjb2xvcnMKZ2dwbG90KHRvcF9nZW5lcywgYWVzKHggPSByZW9yZGVyKGdlbmUsIGF2Z19sb2dGQyksIHkgPSBhdmdfbG9nRkMsIGZpbGwgPSBhdmdfbG9nRkMgPiAwKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgY29vcmRfZmxpcCgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJibHVlIiwgInJlZCIpKSArICAjIFJlZCBmb3IgdXByZWd1bGF0ZWQsIEJsdWUgZm9yIGRvd25yZWd1bGF0ZWQKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVG9wIDMwIFVwcmVndWxhdGVkIGFuZCBEb3ducmVndWxhdGVkIEdlbmVzIiwKICAgICAgIHggPSAiR2VuZSIsCiAgICAgICB5ID0gIkxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgZmlsbCA9ICJFeHByZXNzaW9uIikKCiMgRm9yIHNlcGFyYXRlIHBsb3RzIGZvciB1cHJlZ3VsYXRlZCBhbmQgZG93bnJlZ3VsYXRlZCBnZW5lcwpnZ3Bsb3QodG9wXzMwX3VwLCBhZXMoeCA9IHJlb3JkZXIoZ2VuZSwgYXZnX2xvZ0ZDKSwgeSA9IGF2Z19sb2dGQywgZmlsbCA9IGF2Z19sb2dGQyA+IDApKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsKICBjb29yZF9mbGlwKCkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoInJlZCIsICJibHVlIikpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVG9wIDMwIFVwcmVndWxhdGVkIEdlbmVzIiwKICAgICAgIHggPSAiR2VuZSIsCiAgICAgICB5ID0gIkxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgZmlsbCA9ICJFeHByZXNzaW9uIikKCmdncGxvdCh0b3BfMzBfZG93biwgYWVzKHggPSByZW9yZGVyKGdlbmUsIGF2Z19sb2dGQyksIHkgPSBhdmdfbG9nRkMsIGZpbGwgPSBhdmdfbG9nRkMgPCAwKSkgKyAgIyA8IDAgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKICBnZW9tX2JhcihzdGF0ID0gImlkZW50aXR5IikgKwogIGNvb3JkX2ZsaXAoKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJyZWQiKSkgKyAgIyBSZWQgZm9yIHVwcmVndWxhdGVkLCBCbHVlIGZvciBkb3ducmVndWxhdGVkCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIlRvcCAzMCBEb3ducmVndWxhdGVkIEdlbmVzIiwKICAgICAgIHggPSAiR2VuZSIsCiAgICAgICB5ID0gIkxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgZmlsbCA9ICJFeHByZXNzaW9uIikKCgpgYGAKCgoKIyA1LiAgVm9sY2FubyBQbG90CmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQoKIyBWb2xjYW5vIHBsb3Qgd2l0aCBsYWJlbGVkIHRvcCBnZW5lcwp2b2xjYW5vX3Bsb3QgPC0gZ2dwbG90KHRvcF9nZW5lcywgYWVzKHggPSBhdmdfbG9nRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGF2Z19sb2dGQyksIHNpemUgPSAzLCBhbHBoYSA9IDAuNykgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50MigKICAgIGxvdyA9ICJibHVlIiwgCiAgICBtaWQgPSAiZ3JleSIsIAogICAgaGlnaCA9ICJyZWQiLCAKICAgIG1pZHBvaW50ID0gbWVkaWFuKHRvcF9nZW5lcyRhdmdfbG9nRkMpCiAgKSArCiAgZ2VvbV90ZXh0X3JlcGVsKAogICAgYWVzKGxhYmVsID0gZ2VuZSksICAjIExhYmVsIGdlbmVzCiAgICBzaXplID0gMywgCiAgICBtYXgub3ZlcmxhcHMgPSAyMCAgIyBBZGp1c3QgdG8gYXZvaWQgbGFiZWwgY3Jvd2RpbmcKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJWb2xjYW5vIFBsb3Qgb2YgVG9wIDMwIEJpb21hcmtlcnMiLAogICAgeCA9ICJsb2cyIEZvbGQgQ2hhbmdlIChhdmdfbG9nRkMpIiwKICAgIHkgPSAiLWxvZzEwKEFkanVzdGVkIHAtdmFsdWUpIiwKICAgIGNvbG9yID0gIkZvbGQgQ2hhbmdlIgogICkKCnByaW50KHZvbGNhbm9fcGxvdCkKYGBgCgojIDYuICBCYXIgUGxvdCBvZiBUb3AgR2VuZXMgYnkgRm9sZCBDaGFuZ2UKYGBge3IgLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CiMgQmFyIHBsb3QgKHNvcnRlZCBieSBmb2xkIGNoYW5nZSkKYmFyX3Bsb3QgPC0gZ2dwbG90KHRvcF9nZW5lcywgCiAgICAgICBhZXMoeCA9IHJlb3JkZXIoZ2VuZSwgYXZnX2xvZ0ZDKSwgeSA9IGF2Z19sb2dGQywgCiAgICAgICAgICAgZmlsbCA9IGF2Z19sb2dGQykpICsKICBnZW9tX2NvbCgpICsKICBzY2FsZV9maWxsX2dyYWRpZW50MigKICAgIGxvdyA9ICJibHVlIiwgCiAgICBtaWQgPSAid2hpdGUiLCAKICAgIGhpZ2ggPSAicmVkIiwgCiAgICBtaWRwb2ludCA9IG1lZGlhbih0b3BfZ2VuZXMkYXZnX2xvZ0ZDKQogICkgKwogIGNvb3JkX2ZsaXAoKSArICAjIEhvcml6b250YWwgYmFycwogIHRoZW1lX21pbmltYWwoKSArCiAgbGFicygKICAgIHRpdGxlID0gIlRvcCAzMCBCaW9tYXJrZXJzIGJ5IGxvZzIgRm9sZCBDaGFuZ2UiLAogICAgeCA9ICJHZW5lIiwKICAgIHkgPSAiYXZnX2xvZ0ZDIgogICkKCnByaW50KGJhcl9wbG90KQpgYGAKCiMgNy4gIGRvdHBsb3Qgb2YgRXhwcmVzc2lvbiBQcmV2YWxlbmNlCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgRG90IHBsb3QgY29tcGFyaW5nIHBjdC4xIHZzIHBjdC4yCmRvdF9wbG90IDwtIGdncGxvdCh0b3BfZ2VuZXMsIGFlcyh4ID0gTWFsaWduYW50LnBjdCwgeSA9IENvbnRyb2wucGN0LCAKICAgICAgICAgICAgICAgICAgc2l6ZSA9IGF2Z19sb2dGQywgY29sb3IgPSBhdmdfbG9nRkMpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuOCkgKwogIGdlb21fdGV4dF9yZXBlbChhZXMobGFiZWwgPSBnZW5lKSwgc2l6ZSA9IDMsIG1heC5vdmVybGFwcyA9IDIwKSArCiAgc2NhbGVfY29sb3JfZ3JhZGllbnQyKAogICAgbG93ID0gImJsdWUiLCAKICAgIG1pZCA9ICJncmV5IiwgCiAgICBoaWdoID0gInJlZCIsIAogICAgbWlkcG9pbnQgPSBtZWRpYW4odG9wX2dlbmVzJGF2Z19sb2dGQykKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJFeHByZXNzaW9uIFByZXZhbGVuY2U6IFRhcmdldCBHcm91cCAocGN0LjEpIHZzIENvbnRyb2wgKHBjdC4yKSIsCiAgICB4ID0gIkV4cHJlc3Npb24gaW4gVGFyZ2V0IEdyb3VwIChwY3QuMSkiLAogICAgeSA9ICJFeHByZXNzaW9uIGluIENvbnRyb2wgKHBjdC4yKSIsCiAgICBjb2xvciA9ICJGb2xkIENoYW5nZSIsCiAgICBzaXplID0gIkZvbGQgQ2hhbmdlIgogICkKCnByaW50KGRvdF9wbG90KQpgYGAKIyA4LiAgZG90cGxvdCBvZiBNZWFuIEV4cHJlc3Npb24gUHJldmFsZW5jZQpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIERvdCBwbG90IGNvbXBhcmluZyBwY3QuMSB2cyBwY3QuMgpkb3RfcGxvdCA8LSBnZ3Bsb3QodG9wX2dlbmVzLCBhZXMoeCA9IE1hbGlnbmFudC5leHAsIHkgPSBDb250cm9sLmV4cCwgCiAgICAgICAgICAgICAgICAgIHNpemUgPSBhdmdfbG9nRkMsIGNvbG9yID0gYXZnX2xvZ0ZDKSkgKwogIGdlb21fcG9pbnQoYWxwaGEgPSAwLjgpICsKICBnZW9tX3RleHRfcmVwZWwoYWVzKGxhYmVsID0gZ2VuZSksIHNpemUgPSAzLCBtYXgub3ZlcmxhcHMgPSAyMCkgKwogIHNjYWxlX2NvbG9yX2dyYWRpZW50MigKICAgIGxvdyA9ICJibHVlIiwgCiAgICBtaWQgPSAiZ3JleSIsIAogICAgaGlnaCA9ICJyZWQiLCAKICAgIG1pZHBvaW50ID0gbWVkaWFuKHRvcF9nZW5lcyRhdmdfbG9nRkMpCiAgKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKAogICAgdGl0bGUgPSAiRXhwcmVzc2lvbiBQcmV2YWxlbmNlOiBUYXJnZXQgR3JvdXAgKGV4cC4xKSB2cyBDb250cm9sIChleHAuMikiLAogICAgeCA9ICJFeHByZXNzaW9uIGluIFRhcmdldCBHcm91cCAoZXhwLjEpIiwKICAgIHkgPSAiRXhwcmVzc2lvbiBpbiBDb250cm9sIChleHAuMikiLAogICAgY29sb3IgPSAiRm9sZCBDaGFuZ2UiLAogICAgc2l6ZSA9ICJGb2xkIENoYW5nZSIKICApCgpwcmludChkb3RfcGxvdCkKCmBgYAoKCgoKCgoKCiMgOS4gIEZlYXR1cmVQbG90IGZvciBUb3AzMCBVUApgYGB7ciAsIGZpZy5oZWlnaHQ9MTYsIGZpZy53aWR0aD0yMH0KRmVhdHVyZVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzMwX3VwJGdlbmVbMToxMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgoKRmVhdHVyZVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzMwX3VwJGdlbmVbMTE6MjBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKRmVhdHVyZVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzMwX3VwJGdlbmVbMjE6MzBdLCAKICAgICAgICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwgCiAgICAgICAgICAgICBjb2xzID0gYygibGlnaHRibHVlIiwgInJlZCIpLCAgIyBDdXN0b20gY29sb3IgZ3JhZGllbnQgZnJvbSBsaWdodCBibHVlIHRvIHJlZAogICAgICAgICAgICAgbGFiZWwgPSBUUlVFKQoKCmBgYAoKCgojIDEwLiAgRmVhdHVyZVBsb3QgZm9yIFRvcDMwIERPV04KYGBge3IgLCBmaWcuaGVpZ2h0PTE2LCBmaWcud2lkdGg9MjB9CkZlYXR1cmVQbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICBmZWF0dXJlcyA9IHRvcF8zMF9kb3duJGdlbmVbMToxMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgoKRmVhdHVyZVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICAgICAgICAgICAgIGZlYXR1cmVzID0gdG9wXzMwX2Rvd24kZ2VuZVsxMToyMF0sIAogICAgICAgICAgICAgcmVkdWN0aW9uID0gInVtYXAiLCAKICAgICAgICAgICAgIGNvbHMgPSBjKCJsaWdodGJsdWUiLCAicmVkIiksICAjIEN1c3RvbSBjb2xvciBncmFkaWVudCBmcm9tIGxpZ2h0IGJsdWUgdG8gcmVkCiAgICAgICAgICAgICBsYWJlbCA9IFRSVUUpCgpGZWF0dXJlUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgZmVhdHVyZXMgPSB0b3BfMzBfZG93biRnZW5lWzIxOjMwXSwgCiAgICAgICAgICAgICByZWR1Y3Rpb24gPSAidW1hcCIsIAogICAgICAgICAgICAgY29scyA9IGMoImxpZ2h0Ymx1ZSIsICJyZWQiKSwgICMgQ3VzdG9tIGNvbG9yIGdyYWRpZW50IGZyb20gbGlnaHQgYmx1ZSB0byByZWQKICAgICAgICAgICAgIGxhYmVsID0gVFJVRSkKCmBgYA==