1. load libraries
3. Create the EnhancedVolcano plot
library(dplyr)
library(EnhancedVolcano)
# Assuming you have a data frame named Malignant_CD4Tcells_vs_Normal_CD4Tcells
# Filter genes based on lowest p-values but include all genes
filtered_genes <- Malignant_CD4Tcells_vs_Normal_CD4Tcells %>%
arrange(p_val_adj, desc(abs(avg_logFC)))
# Create the EnhancedVolcano plot with the filtered data
EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_logFC) >= 1.0, filtered_genes$gene, NA),
x = "avg_logFC",
y = "p_val_adj",
title = "Malignant CD4 T cells(cell lines) vs normal CD4 T cells",
pCutoff = 1e-10,
FCcutoff = 1.5,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = FALSE, # Set to FALSE to remove boxed labels
pointSize = 3.0,
labSize = 5.0,
col = c('grey70', 'black', 'blue', 'red'), # Customize point colors
selectLab = filtered_genes$gene[filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_logFC) >= 1.0] # Only label significant genes
)

EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_logFC) >= 1.0, filtered_genes$gene, NA),
x = "avg_logFC",
y = "p_val_adj",
title = "Malignant CD4 T cells (cell lines) vs Normal CD4 T cells",
subtitle = "Highlighting differentially expressed genes",
pCutoff = 1e-10,
FCcutoff = 1.5,
legendPosition = 'right',
colAlpha = 0.8, # Slight transparency for non-significant points
col = c('grey70', 'black', 'blue', 'red'), # Custom color scheme
gridlines.major = TRUE,
gridlines.minor = FALSE,
selectLab = filtered_genes$gene[filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_logFC) >= 1.0]
)

NA
NA
7. Save Hallmark and kegg to CSV
# Assuming you have the results stored in fgsea_result_hallmark and fgsea_result_kegg
# Flatten the list columns into character strings for Hallmark results
fgsea_result_hallmark_flattened <- fgsea_result %>%
mutate(across(where(is.list), ~ sapply(., toString)))
# Write the flattened Hallmark results to a CSV file
write.csv(fgsea_result_hallmark_flattened, "fgsea_results_hallmark.csv", row.names = FALSE)
# Flatten the list columns into character strings for KEGG results
fgsea_result_kegg_flattened <- fgsea_result_kegg %>%
mutate(across(where(is.list), ~ sapply(., toString)))
# Write the flattened KEGG results to a CSV file
write.csv(fgsea_result_kegg_flattened, "fgsea_results_kegg.csv", row.names = FALSE)
ggplot(data.frame(gene_symbol = names(gene_list)[1:50], ranks = gene_list[1:50]), aes(gene_symbol, ranks)) +
geom_point() +
theme_classic() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))

8. Hallmark genes found in multiple pathways
# Load necessary libraries
library(dplyr)
library(tidyr)
library(ggplot2)
# Assuming 'fgsea_results' is the output of your fgsea analysis
# Step 1: Extract the leading edge genes for each significant pathway
# 'leadingEdge' contains the gene names that contribute to the enrichment of the pathway
significant_gene_sets <- fgsea_result %>%
filter(padj < 0.05) %>%
select(pathway, leadingEdge)
# Step 2: Unnest the leadingEdge column (convert list to rows)
significant_gene_sets <- significant_gene_sets %>%
unnest(cols = leadingEdge)
# Step 3: Count how many times each gene appears across pathways
gene_count <- significant_gene_sets %>%
group_by(leadingEdge) %>%
summarise(count = n()) %>%
arrange(desc(count)) # Arrange genes by the number of pathways they appear in
# Step 4: Visualize the top regulator genes (genes that appear in multiple pathways)
top_regulator_genes <- gene_count %>%
filter(count > 1) # Genes involved in more than one pathway
# Plot top regulator genes involved in multiple pathways
ggplot(top_regulator_genes, aes(x = reorder(leadingEdge, -count), y = count)) +
geom_bar(stat = "identity", fill = "salmon") +
coord_flip() +
labs(title = "Top Regulator Genes Involved in Multiple Pathways",
x = "Gene",
y = "Number of Pathways") +
theme_minimal()

# Step 5: Output the gene counts to a CSV file for further inspection
write.csv(gene_count, "gene_count_in_multiple_pathways.csv")
8. Hallmark genes found in multiple pathways
# Load necessary libraries
library(dplyr)
library(tidyr)
library(ggplot2)
# Assuming 'fgsea_results' is the output of your fgsea analysis
# Step 1: Extract the leading edge genes for each significant pathway
# 'leadingEdge' contains the gene names that contribute to the enrichment of the pathway
significant_gene_sets <- fgsea_result_kegg %>%
filter(padj < 0.05) %>%
select(pathway, leadingEdge)
# Step 2: Unnest the leadingEdge column (convert list to rows)
significant_gene_sets <- significant_gene_sets %>%
unnest(cols = leadingEdge)
# Step 3: Count how many times each gene appears across pathways
gene_count <- significant_gene_sets %>%
group_by(leadingEdge) %>%
summarise(count = n()) %>%
arrange(desc(count)) # Arrange genes by the number of pathways they appear in
# Step 4: Visualize the top regulator genes (genes that appear in multiple pathways)
top_regulator_genes <- gene_count %>%
filter(count > 1) # Genes involved in more than one pathway
# Plot top regulator genes involved in multiple pathways
ggplot(top_regulator_genes, aes(x = reorder(leadingEdge, -count), y = count)) +
geom_bar(stat = "identity", fill = "salmon") +
coord_flip() +
labs(title = "Top Regulator Genes Involved in Multiple Pathways",
x = "Gene",
y = "Number of Pathways") +
theme_minimal()

# Step 5: Output the gene counts to a CSV file for further inspection
write.csv(gene_count, "gene_count_in_multiple_pathways.csv")
LS0tCnRpdGxlOiAiRkdTRUEtIG9mIE1hbGlnbmFudCBDRDRUY2VsbHMgdnMgQ29udHJvbChOb3JtYWwgQ0Q0IFRjZWxscykiCmF1dGhvcjogTmFzaXIgTWFobW9vZCBBYmJhc2kKZGF0ZTogImByIFN5cy5EYXRlKClgIgpvdXRwdXQ6CiAgI3JtZGZvcm1hdHM6OnJlYWR0aGVkb3duCiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogdHJ1ZQogICAgdG9jX2Zsb2F0OiB0cnVlCiAgICB0b2NfY29sbGFwc2VkOiB0cnVlCi0tLQoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0Kc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQpsaWJyYXJ5KFNldXJhdERhdGEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGhhcm1vbnkpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShSdHNuZSkKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCn0pCiAgCmBgYAoKIyAyLiBQZXJmb3JtIERFIGFuYWx5c2lzIHVzaW5nIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyBnZW5lcwpgYGB7ciBkYXRhMSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgpNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgPC0gcmVhZC5jc3YoIjEtUHNldWRvYnVsa19ERXNlcTJfTFJUX0RFX3dpdGhfbGlicmEuY3N2IiwgaGVhZGVyID0gVCkKYGBgCgojIDMuIENyZWF0ZSB0aGUgRW5oYW5jZWRWb2xjYW5vIHBsb3QKYGBge3IgZW5oYW5jZWRWLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTZ9CgpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKCiMgQXNzdW1pbmcgeW91IGhhdmUgYSBkYXRhIGZyYW1lIG5hbWVkIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscwojIEZpbHRlciBnZW5lcyBiYXNlZCBvbiBsb3dlc3QgcC12YWx1ZXMgYnV0IGluY2x1ZGUgYWxsIGdlbmVzCmZpbHRlcmVkX2dlbmVzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBhcnJhbmdlKHBfdmFsX2FkaiwgZGVzYyhhYnMoYXZnX2xvZ0ZDKSkpCgojIENyZWF0ZSB0aGUgRW5oYW5jZWRWb2xjYW5vIHBsb3Qgd2l0aCB0aGUgZmlsdGVyZWQgZGF0YQpFbmhhbmNlZFZvbGNhbm8oCiAgZmlsdGVyZWRfZ2VuZXMsIAogIGxhYiA9IGlmZWxzZShmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nRkMpID49IDEuMCwgZmlsdGVyZWRfZ2VuZXMkZ2VuZSwgTkEpLAogIHggPSAiYXZnX2xvZ0ZDIiwgCiAgeSA9ICJwX3ZhbF9hZGoiLAogIHRpdGxlID0gIk1hbGlnbmFudCBDRDQgVCBjZWxscyhjZWxsIGxpbmVzKSB2cyBub3JtYWwgQ0Q0IFQgY2VsbHMiLAogIHBDdXRvZmYgPSAxZS0xMCwKICBGQ2N1dG9mZiA9IDEuNSwKICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsIAogIGxhYkNvbCA9ICdibGFjaycsCiAgbGFiRmFjZSA9ICdib2xkJywKICBib3hlZExhYmVscyA9IEZBTFNFLCAgIyBTZXQgdG8gRkFMU0UgdG8gcmVtb3ZlIGJveGVkIGxhYmVscwogIHBvaW50U2l6ZSA9IDMuMCwKICBsYWJTaXplID0gNS4wLAogIGNvbCA9IGMoJ2dyZXk3MCcsICdibGFjaycsICdibHVlJywgJ3JlZCcpLCAgIyBDdXN0b21pemUgcG9pbnQgY29sb3JzCiAgc2VsZWN0TGFiID0gZmlsdGVyZWRfZ2VuZXMkZ2VuZVtmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nRkMpID49IDEuMF0gICMgT25seSBsYWJlbCBzaWduaWZpY2FudCBnZW5lcwopCgoKCkVuaGFuY2VkVm9sY2FubygKICBmaWx0ZXJlZF9nZW5lcywgCiAgbGFiID0gaWZlbHNlKGZpbHRlcmVkX2dlbmVzJHBfdmFsX2FkaiA8PSAwLjA1ICYgYWJzKGZpbHRlcmVkX2dlbmVzJGF2Z19sb2dGQykgPj0gMS4wLCBmaWx0ZXJlZF9nZW5lcyRnZW5lLCBOQSksCiAgeCA9ICJhdmdfbG9nRkMiLCAKICB5ID0gInBfdmFsX2FkaiIsCiAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzIChjZWxsIGxpbmVzKSB2cyBOb3JtYWwgQ0Q0IFQgY2VsbHMiLAogIHN1YnRpdGxlID0gIkhpZ2hsaWdodGluZyBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMiLAogIHBDdXRvZmYgPSAxZS0xMCwKICBGQ2N1dG9mZiA9IDEuNSwKICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgY29sQWxwaGEgPSAwLjgsICAjIFNsaWdodCB0cmFuc3BhcmVuY3kgZm9yIG5vbi1zaWduaWZpY2FudCBwb2ludHMKICBjb2wgPSBjKCdncmV5NzAnLCAnYmxhY2snLCAnYmx1ZScsICdyZWQnKSwgICMgQ3VzdG9tIGNvbG9yIHNjaGVtZQogIGdyaWRsaW5lcy5tYWpvciA9IFRSVUUsCiAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UsCiAgc2VsZWN0TGFiID0gZmlsdGVyZWRfZ2VuZXMkZ2VuZVtmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nRkMpID49IDEuMF0KKSAKCgpgYGAKCiMgNC4gIFBlcmZvcm0gRmFzdCBHU0VBIHVzaW5nIEhhbGxtYXJrIEdlbmUgU2V0cwpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcmllcwpsaWJyYXJ5KGZnc2VhKQpsaWJyYXJ5KG1zaWdkYnIpCmxpYnJhcnkoZHBseXIpCgojIE9idGFpbiBIYWxsbWFyayBnZW5lIHNldHMgZnJvbSBtc2lnZGJyCmhhbGxtYXJrX2dlbmVzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJIIikKCiMgQ29udmVydCB0aGUgZ2VuZSBzZXRzIHRvIGEgbGlzdCBmb3JtYXQgZm9yIGZnc2VhCmhhbGxtYXJrX2xpc3QgPC0gaGFsbG1hcmtfZ2VuZXMgJT4lCiAgc3BsaXQoeCA9IC4kZ2VuZV9zeW1ib2wsIGYgPSAuJGdzX25hbWUpCgojIEFzc3VtaW5nIHlvdSBoYXZlIGEgZGF0YSBmcmFtZSBuYW1lZCBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMKIyBDcmVhdGUgYSByYW5rZWQgbGlzdCB3aXRoIFNJR05FRCBtZXRyaWMKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBtdXRhdGUocmFua19tZXRyaWMgPSBhdmdfbG9nRkMgKiAtbG9nMTAocF92YWxfYWRqKSkKCgojIEVuc3VyZSBubyBOQSB2YWx1ZXMgaW4gcmFua19tZXRyaWMKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBmaWx0ZXIoIWlzLm5hKHJhbmtfbWV0cmljKSkKCiMgQ3JlYXRlIGEgbmFtZWQgdmVjdG9yIGZvciByYW5raW5nCmdlbmVfbGlzdCA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcmFua19tZXRyaWMKbmFtZXMoZ2VuZV9saXN0KSA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZQoKIyBSZW1vdmUgaW5maW5pdGUgdmFsdWVzIGFuZCBzb3J0IGluIGRlY3JlYXNpbmcgb3JkZXIKZ2VuZV9saXN0IDwtIGdlbmVfbGlzdFtpcy5maW5pdGUoZ2VuZV9saXN0KV0KZ2VuZV9saXN0IDwtIHNvcnQoZ2VuZV9saXN0LCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgUGVyZm9ybSBmYXN0IEdTRUEgdXNpbmcgZmdzZWFNdWx0aWxldmVsCmZnc2VhX3Jlc3VsdCA8LSBmZ3NlYShwYXRod2F5cyA9IGhhbGxtYXJrX2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzID0gZ2VuZV9saXN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVwcyA9IDAuMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5TaXplID0gMTUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4U2l6ZSA9IDUwMCkgICMgTm8gbmVlZCBmb3IgbnBlcm0KCiMgVmlldyB0aGUgZmdzZWEgcmVzdWx0cwpoZWFkKGZnc2VhX3Jlc3VsdFtvcmRlcihwdmFsKSwgXSkKCgpgYGAKCgoKIyA0LiAgUGVyZm9ybSBWaXN1YWxpemF0aW9uIG9mIGZnc2VxIHVzaW5nIEhhbGxtYXJrIEdlbmUgU2V0cwpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkoZmdzZWEpCmxpYnJhcnkoZ2dwbG90MikKCiMgUGxvdCB0aGUgdG9wIHBhdGh3YXkKdG9wX3BhdGh3YXkgPC0gZmdzZWFfcmVzdWx0W29yZGVyKGZnc2VhX3Jlc3VsdCRwYWRqKSwgXVsxLCBdCnBsb3RFbnJpY2htZW50KGhhbGxtYXJrX2xpc3RbW3RvcF9wYXRod2F5JHBhdGh3YXldXSwgZ2VuZV9saXN0KSArCiAgbGFicyh0aXRsZSA9IHRvcF9wYXRod2F5JHBhdGh3YXkpCgp0b3BQYXRod2F5c1VwIDwtIGZnc2VhX3Jlc3VsdFtFUyA+IDBdW2hlYWQob3JkZXIocGFkaiksIG49MTApLCBwYXRod2F5XQp0b3BQYXRod2F5c0Rvd24gPC0gZmdzZWFfcmVzdWx0W0VTIDwgMF1baGVhZChvcmRlcihwYWRqKSwgbj0xMCksIHBhdGh3YXldCnRvcFBhdGh3YXlzIDwtIGModG9wUGF0aHdheXNVcCwgcmV2KHRvcFBhdGh3YXlzRG93bikpCnBsb3RHc2VhVGFibGUoaGFsbG1hcmtfbGlzdFt0b3BQYXRod2F5c10sIGdlbmVfbGlzdCwgZmdzZWFfcmVzdWx0LCAKICAgICAgICAgICAgICBnc2VhUGFyYW09MC41KQoKCmBgYAoKIyMgLiBWaXN1YWxpemF0aW9uLUhhbGxtYXJrCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmZnc2VhUmVzVGlkeSA8LSBmZ3NlYV9yZXN1bHQgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgYXJyYW5nZShkZXNjKE5FUykpCgojIFNob3cgaW4gYSBuaWNlIHRhYmxlLCBleGNsdWRpbmcgYW55IGNvbHVtbnMgdGhhdCBkbyBub3QgZXhpc3QKZmdzZWFSZXNUaWR5ICU+JSAKICBkcGx5cjo6c2VsZWN0KC1sZWFkaW5nRWRnZSwgLUVTKSAlPiUgCiAgYXJyYW5nZShwYWRqKSAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgpCgpnZ3Bsb3QoZmdzZWFSZXNUaWR5LCBhZXMocmVvcmRlcihwYXRod2F5LCBORVMpLCBORVMpKSArCiAgZ2VvbV9jb2woYWVzKGZpbGw9cGFkajwwLjA1KSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh4PSJQYXRod2F5IiwgeT0iTm9ybWFsaXplZCBFbnJpY2htZW50IFNjb3JlIiwKICAgICAgIHRpdGxlPSJIYWxsbWFyayBwYXRod2F5cyBORVMgZnJvbSBmZ3NlYSIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVFJVRSIgPSAicmVkIiwgIkZBTFNFIiA9ICJncmV5IikpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICAjIEFkanVzdCBheGlzIHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKCgoKYGBgCgojIDUuIE9idGFpbiBLRUdHIEdlbmUgU2V0cyBhbmQgUGVyZm9ybSBmZ3NlYSBVc2luZyBLRUdHIFBhdGh3YXlzCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZmdzZWEpCmxpYnJhcnkobXNpZ2RicikKbGlicmFyeShkcGx5cikKbGlicmFyeShwaGVhdG1hcCkKCiMgT2J0YWluIEtFR0cgTGVnYWN5IGdlbmUgc2V0cyBmcm9tIG1zaWdkYnIKa2VnZ19nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiLCBzdWJjb2xsZWN0aW9uID0gIkNQOktFR0dfTEVHQUNZIikKCiMgQ29udmVydCB0aGUgZ2VuZSBzZXRzIHRvIGEgbGlzdCBmb3JtYXQgZm9yIGZnc2VhCmtlZ2dfbGlzdCA8LSBrZWdnX2dlbmVzICU+JQogIHNwbGl0KHggPSAuJGdlbmVfc3ltYm9sLCBmID0gLiRnc19uYW1lKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgbmFtZWQgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3QgYmFzZWQgb24gYXZnX2xvZ0ZDIGFuZCBwX3ZhbF9hZGoKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBtdXRhdGUocmFua19tZXRyaWMgPSBhdmdfbG9nRkMgKiAtbG9nMTAocF92YWxfYWRqKSkKCiMgRW5zdXJlIG5vIE5BIHZhbHVlcyBpbiByYW5rX21ldHJpYwpNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzICU+JQogIGZpbHRlcighaXMubmEocmFua19tZXRyaWMpKQoKIyBDcmVhdGUgYSBuYW1lZCB2ZWN0b3IgZm9yIHJhbmtpbmcKZ2VuZV9saXN0IDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRyYW5rX21ldHJpYwpuYW1lcyhnZW5lX2xpc3QpIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyRnZW5lCgojIFNvcnQgdGhlIG5hbWVkIHZlY3RvciBpbiBkZWNyZWFzaW5nIG9yZGVyCmdlbmVfbGlzdCA8LSBzb3J0KGdlbmVfbGlzdCwgZGVjcmVhc2luZyA9IFRSVUUpCgpnZW5lX2xpc3QgPC0gZ2VuZV9saXN0W2lzLmZpbml0ZShnZW5lX2xpc3QpXQoKIyBQZXJmb3JtIGZhc3QgR1NFQSB1c2luZyBLRUdHIHBhdGh3YXlzCmZnc2VhX3Jlc3VsdF9rZWdnIDwtIGZnc2VhKHBhdGh3YXlzID0ga2VnZ19saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHMgPSBnZW5lX2xpc3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGVwcz0wLjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pblNpemUgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4U2l6ZSA9IDUwMCkgIAoKCiMgVmlldyB0aGUgZmdzZWEgcmVzdWx0cwpoZWFkKGZnc2VhX3Jlc3VsdF9rZWdnW29yZGVyKHB2YWwpLCBdKQoKCmBgYAoKIyA2LiAgUGVyZm9ybSBWaXN1YWxpemF0aW9uIG9mIGZnc2VxIHVzaW5nIEtFR0cgR2VuZSBTZXRzCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShmZ3NlYSkKbGlicmFyeShnZ3Bsb3QyKQoKIyBQbG90IHRoZSB0b3AgcGF0aHdheQp0b3BfcGF0aHdheSA8LSBmZ3NlYV9yZXN1bHRfa2VnZ1tvcmRlcihmZ3NlYV9yZXN1bHRfa2VnZyRwYWRqKSwgXVsxLCBdCnBsb3RFbnJpY2htZW50KGtlZ2dfbGlzdFtbdG9wX3BhdGh3YXkkcGF0aHdheV1dLCBnZW5lX2xpc3QpICsKICBsYWJzKHRpdGxlID0gdG9wX3BhdGh3YXkkcGF0aHdheSkKCnRvcFBhdGh3YXlzVXAgPC0gZmdzZWFfcmVzdWx0X2tlZ2dbRVMgPiAwXVtoZWFkKG9yZGVyKHBhZGopLCBuPTEwKSwgcGF0aHdheV0KdG9wUGF0aHdheXNEb3duIDwtIGZnc2VhX3Jlc3VsdF9rZWdnW0VTIDwgMF1baGVhZChvcmRlcihwYWRqKSwgbj0xMCksIHBhdGh3YXldCnRvcFBhdGh3YXlzIDwtIGModG9wUGF0aHdheXNVcCwgcmV2KHRvcFBhdGh3YXlzRG93bikpCnBsb3RHc2VhVGFibGUoa2VnZ19saXN0W3RvcFBhdGh3YXlzXSwgZ2VuZV9saXN0LCBmZ3NlYV9yZXN1bHRfa2VnZywgCiAgICAgICAgICAgICAgZ3NlYVBhcmFtPTAuNSkKCgpgYGAKCiMjIC4gVmlzdWFsaXphdGlvbi1LZWdnMQpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpmZ3NlYVJlc1RpZHkgPC0gZmdzZWFfcmVzdWx0X2tlZ2cgJT4lCiAgYXNfdGliYmxlKCkgJT4lCiAgYXJyYW5nZShkZXNjKE5FUykpCgojIFNob3cgaW4gYSBuaWNlIHRhYmxlLCBleGNsdWRpbmcgYW55IGNvbHVtbnMgdGhhdCBkbyBub3QgZXhpc3QKZmdzZWFSZXNUaWR5ICU+JSAKICBkcGx5cjo6c2VsZWN0KC1sZWFkaW5nRWRnZSwgLUVTKSAlPiUgCiAgYXJyYW5nZShwYWRqKSAlPiUgCiAgRFQ6OmRhdGF0YWJsZSgpCgpnZ3Bsb3QoZmdzZWFSZXNUaWR5LCBhZXMocmVvcmRlcihwYXRod2F5LCBORVMpLCBORVMpKSArCiAgZ2VvbV9jb2woYWVzKGZpbGw9cGFkajwwLjA1KSkgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh4PSJQYXRod2F5IiwgeT0iTm9ybWFsaXplZCBFbnJpY2htZW50IFNjb3JlIiwKICAgICAgIHRpdGxlPSJIYWxsbWFyayBwYXRod2F5cyBORVMgZnJvbSBmZ3NlYSIpICsgCiAgdGhlbWVfbWluaW1hbCgpICsgCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVFJVRSIgPSAicmVkIiwgIkZBTFNFIiA9ICJncmV5IikpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkpICAjIEFkanVzdCBheGlzIHRleHQgc2l6ZSBmb3IgcmVhZGFiaWxpdHkKCgoKYGBgCgojIyAuIFZpc3VhbGl6YXRpb24tS2VnZzIKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBBcnJhbmdlIGJ5IE5FUyBhbmQgc2VsZWN0IHRvcCAyMCB1cCBhbmQgZG93biBwYXRod2F5cwp0b3BVcCA8LSBmZ3NlYVJlc1RpZHkgJT4lCiAgZHBseXI6OmZpbHRlcihORVMgPiAwKSAlPiUKICBkcGx5cjo6YXJyYW5nZShkZXNjKE5FUykpICU+JQogIGRwbHlyOjpzbGljZV9oZWFkKG4gPSAyMCkKCnRvcERvd24gPC0gZmdzZWFSZXNUaWR5ICU+JQogIGRwbHlyOjpmaWx0ZXIoTkVTIDwgMCkgJT4lCiAgZHBseXI6OmFycmFuZ2UoTkVTKSAlPiUKICBkcGx5cjo6c2xpY2VfaGVhZChuID0gMjApCgojIENvbWJpbmUgdGhlIHRvcCB1cCBhbmQgZG93biBwYXRod2F5cwp0b3BQYXRod2F5cyA8LSBkcGx5cjo6YmluZF9yb3dzKHRvcFVwLCB0b3BEb3duKQoKCmdncGxvdCh0b3BQYXRod2F5cywgYWVzKHJlb3JkZXIocGF0aHdheSwgTkVTKSwgTkVTKSkgKwogIGdlb21fY29sKGFlcyhmaWxsID0gcGFkaiA8IDAuMDUpKSArCiAgY29vcmRfZmxpcCgpICsKICBsYWJzKHggPSAiUGF0aHdheSIsIHkgPSAiTm9ybWFsaXplZCBFbnJpY2htZW50IFNjb3JlIiwKICAgICAgIHRpdGxlID0gIlRvcCAyMCBVcCBhbmQgRG93biBLRUdHIFBhdGh3YXlzIE5FUyBmcm9tIEdTRUEiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJUUlVFIiA9ICJyZWQiLCAiRkFMU0UiID0gImdyZXkiKSkKCgoKCmBgYAoKIyA3LiBTYXZlIEhhbGxtYXJrIGFuZCBrZWdnIHRvIENTVgpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKIyBBc3N1bWluZyB5b3UgaGF2ZSB0aGUgcmVzdWx0cyBzdG9yZWQgaW4gZmdzZWFfcmVzdWx0X2hhbGxtYXJrIGFuZCBmZ3NlYV9yZXN1bHRfa2VnZwoKIyBGbGF0dGVuIHRoZSBsaXN0IGNvbHVtbnMgaW50byBjaGFyYWN0ZXIgc3RyaW5ncyBmb3IgSGFsbG1hcmsgcmVzdWx0cwpmZ3NlYV9yZXN1bHRfaGFsbG1hcmtfZmxhdHRlbmVkIDwtIGZnc2VhX3Jlc3VsdCAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmxpc3QpLCB+IHNhcHBseSguLCB0b1N0cmluZykpKQoKIyBXcml0ZSB0aGUgZmxhdHRlbmVkIEhhbGxtYXJrIHJlc3VsdHMgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YoZmdzZWFfcmVzdWx0X2hhbGxtYXJrX2ZsYXR0ZW5lZCwgImZnc2VhX3Jlc3VsdHNfaGFsbG1hcmsuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIEZsYXR0ZW4gdGhlIGxpc3QgY29sdW1ucyBpbnRvIGNoYXJhY3RlciBzdHJpbmdzIGZvciBLRUdHIHJlc3VsdHMKZmdzZWFfcmVzdWx0X2tlZ2dfZmxhdHRlbmVkIDwtIGZnc2VhX3Jlc3VsdF9rZWdnICU+JQogIG11dGF0ZShhY3Jvc3Mod2hlcmUoaXMubGlzdCksIH4gc2FwcGx5KC4sIHRvU3RyaW5nKSkpCgojIFdyaXRlIHRoZSBmbGF0dGVuZWQgS0VHRyByZXN1bHRzIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KGZnc2VhX3Jlc3VsdF9rZWdnX2ZsYXR0ZW5lZCwgImZnc2VhX3Jlc3VsdHNfa2VnZy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCgpnZ3Bsb3QoZGF0YS5mcmFtZShnZW5lX3N5bWJvbCA9IG5hbWVzKGdlbmVfbGlzdClbMTo1MF0sIHJhbmtzID0gZ2VuZV9saXN0WzE6NTBdKSwgYWVzKGdlbmVfc3ltYm9sLCByYW5rcykpICsgCglnZW9tX3BvaW50KCkgKwoJdGhlbWVfY2xhc3NpYygpICsgCgl0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwLCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpCgpgYGAKIyA4LiAgSGFsbG1hcmsgZ2VuZXMgZm91bmQgaW4gbXVsdGlwbGUgcGF0aHdheXMKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQXNzdW1pbmcgJ2Znc2VhX3Jlc3VsdHMnIGlzIHRoZSBvdXRwdXQgb2YgeW91ciBmZ3NlYSBhbmFseXNpcwoKIyBTdGVwIDE6IEV4dHJhY3QgdGhlIGxlYWRpbmcgZWRnZSBnZW5lcyBmb3IgZWFjaCBzaWduaWZpY2FudCBwYXRod2F5CiMgJ2xlYWRpbmdFZGdlJyBjb250YWlucyB0aGUgZ2VuZSBuYW1lcyB0aGF0IGNvbnRyaWJ1dGUgdG8gdGhlIGVucmljaG1lbnQgb2YgdGhlIHBhdGh3YXkKc2lnbmlmaWNhbnRfZ2VuZV9zZXRzIDwtIGZnc2VhX3Jlc3VsdCAlPiUKICBmaWx0ZXIocGFkaiA8IDAuMDUpICU+JQogIHNlbGVjdChwYXRod2F5LCBsZWFkaW5nRWRnZSkKCiMgU3RlcCAyOiBVbm5lc3QgdGhlIGxlYWRpbmdFZGdlIGNvbHVtbiAoY29udmVydCBsaXN0IHRvIHJvd3MpCnNpZ25pZmljYW50X2dlbmVfc2V0cyA8LSBzaWduaWZpY2FudF9nZW5lX3NldHMgJT4lCiAgdW5uZXN0KGNvbHMgPSBsZWFkaW5nRWRnZSkKCiMgU3RlcCAzOiBDb3VudCBob3cgbWFueSB0aW1lcyBlYWNoIGdlbmUgYXBwZWFycyBhY3Jvc3MgcGF0aHdheXMKZ2VuZV9jb3VudCA8LSBzaWduaWZpY2FudF9nZW5lX3NldHMgJT4lCiAgZ3JvdXBfYnkobGVhZGluZ0VkZ2UpICU+JQogIHN1bW1hcmlzZShjb3VudCA9IG4oKSkgJT4lCiAgYXJyYW5nZShkZXNjKGNvdW50KSkgICMgQXJyYW5nZSBnZW5lcyBieSB0aGUgbnVtYmVyIG9mIHBhdGh3YXlzIHRoZXkgYXBwZWFyIGluCgojIFN0ZXAgNDogVmlzdWFsaXplIHRoZSB0b3AgcmVndWxhdG9yIGdlbmVzIChnZW5lcyB0aGF0IGFwcGVhciBpbiBtdWx0aXBsZSBwYXRod2F5cykKdG9wX3JlZ3VsYXRvcl9nZW5lcyA8LSBnZW5lX2NvdW50ICU+JQogIGZpbHRlcihjb3VudCA+IDEpICAjIEdlbmVzIGludm9sdmVkIGluIG1vcmUgdGhhbiBvbmUgcGF0aHdheQoKIyBQbG90IHRvcCByZWd1bGF0b3IgZ2VuZXMgaW52b2x2ZWQgaW4gbXVsdGlwbGUgcGF0aHdheXMKZ2dwbG90KHRvcF9yZWd1bGF0b3JfZ2VuZXMsIGFlcyh4ID0gcmVvcmRlcihsZWFkaW5nRWRnZSwgLWNvdW50KSwgeSA9IGNvdW50KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBmaWxsID0gInNhbG1vbiIpICsKICBjb29yZF9mbGlwKCkgKwogIGxhYnModGl0bGUgPSAiVG9wIFJlZ3VsYXRvciBHZW5lcyBJbnZvbHZlZCBpbiBNdWx0aXBsZSBQYXRod2F5cyIsCiAgICAgICB4ID0gIkdlbmUiLAogICAgICAgeSA9ICJOdW1iZXIgb2YgUGF0aHdheXMiKSArCiAgdGhlbWVfbWluaW1hbCgpCgojIFN0ZXAgNTogT3V0cHV0IHRoZSBnZW5lIGNvdW50cyB0byBhIENTViBmaWxlIGZvciBmdXJ0aGVyIGluc3BlY3Rpb24Kd3JpdGUuY3N2KGdlbmVfY291bnQsICJnZW5lX2NvdW50X2luX211bHRpcGxlX3BhdGh3YXlzLmNzdiIpCgoKYGBgCgoKIyA4LiAgSGFsbG1hcmsgZ2VuZXMgZm91bmQgaW4gbXVsdGlwbGUgcGF0aHdheXMKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgTG9hZCBuZWNlc3NhcnkgbGlicmFyaWVzCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkodGlkeXIpCmxpYnJhcnkoZ2dwbG90MikKCiMgQXNzdW1pbmcgJ2Znc2VhX3Jlc3VsdHMnIGlzIHRoZSBvdXRwdXQgb2YgeW91ciBmZ3NlYSBhbmFseXNpcwoKIyBTdGVwIDE6IEV4dHJhY3QgdGhlIGxlYWRpbmcgZWRnZSBnZW5lcyBmb3IgZWFjaCBzaWduaWZpY2FudCBwYXRod2F5CiMgJ2xlYWRpbmdFZGdlJyBjb250YWlucyB0aGUgZ2VuZSBuYW1lcyB0aGF0IGNvbnRyaWJ1dGUgdG8gdGhlIGVucmljaG1lbnQgb2YgdGhlIHBhdGh3YXkKc2lnbmlmaWNhbnRfZ2VuZV9zZXRzIDwtIGZnc2VhX3Jlc3VsdF9rZWdnICU+JQogIGZpbHRlcihwYWRqIDwgMC4wNSkgJT4lCiAgc2VsZWN0KHBhdGh3YXksIGxlYWRpbmdFZGdlKQoKIyBTdGVwIDI6IFVubmVzdCB0aGUgbGVhZGluZ0VkZ2UgY29sdW1uIChjb252ZXJ0IGxpc3QgdG8gcm93cykKc2lnbmlmaWNhbnRfZ2VuZV9zZXRzIDwtIHNpZ25pZmljYW50X2dlbmVfc2V0cyAlPiUKICB1bm5lc3QoY29scyA9IGxlYWRpbmdFZGdlKQoKIyBTdGVwIDM6IENvdW50IGhvdyBtYW55IHRpbWVzIGVhY2ggZ2VuZSBhcHBlYXJzIGFjcm9zcyBwYXRod2F5cwpnZW5lX2NvdW50IDwtIHNpZ25pZmljYW50X2dlbmVfc2V0cyAlPiUKICBncm91cF9ieShsZWFkaW5nRWRnZSkgJT4lCiAgc3VtbWFyaXNlKGNvdW50ID0gbigpKSAlPiUKICBhcnJhbmdlKGRlc2MoY291bnQpKSAgIyBBcnJhbmdlIGdlbmVzIGJ5IHRoZSBudW1iZXIgb2YgcGF0aHdheXMgdGhleSBhcHBlYXIgaW4KCiMgU3RlcCA0OiBWaXN1YWxpemUgdGhlIHRvcCByZWd1bGF0b3IgZ2VuZXMgKGdlbmVzIHRoYXQgYXBwZWFyIGluIG11bHRpcGxlIHBhdGh3YXlzKQp0b3BfcmVndWxhdG9yX2dlbmVzIDwtIGdlbmVfY291bnQgJT4lCiAgZmlsdGVyKGNvdW50ID4gMSkgICMgR2VuZXMgaW52b2x2ZWQgaW4gbW9yZSB0aGFuIG9uZSBwYXRod2F5CgojIFBsb3QgdG9wIHJlZ3VsYXRvciBnZW5lcyBpbnZvbHZlZCBpbiBtdWx0aXBsZSBwYXRod2F5cwpnZ3Bsb3QodG9wX3JlZ3VsYXRvcl9nZW5lcywgYWVzKHggPSByZW9yZGVyKGxlYWRpbmdFZGdlLCAtY291bnQpLCB5ID0gY291bnQpKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIGZpbGwgPSAic2FsbW9uIikgKwogIGNvb3JkX2ZsaXAoKSArCiAgbGFicyh0aXRsZSA9ICJUb3AgUmVndWxhdG9yIEdlbmVzIEludm9sdmVkIGluIE11bHRpcGxlIFBhdGh3YXlzIiwKICAgICAgIHggPSAiR2VuZSIsCiAgICAgICB5ID0gIk51bWJlciBvZiBQYXRod2F5cyIpICsKICB0aGVtZV9taW5pbWFsKCkKCiMgU3RlcCA1OiBPdXRwdXQgdGhlIGdlbmUgY291bnRzIHRvIGEgQ1NWIGZpbGUgZm9yIGZ1cnRoZXIgaW5zcGVjdGlvbgp3cml0ZS5jc3YoZ2VuZV9jb3VudCwgImdlbmVfY291bnRfaW5fbXVsdGlwbGVfcGF0aHdheXMuY3N2IikKCgpgYGA=