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==