1. load libraries
3. Create the EnhancedVolcano plot
EnhancedVolcano(Malignant_CD4Tcells_vs_Normal_CD4Tcells,
lab = Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene,
x = "avg_log2FC",
y = "p_val_adj",
title = "MAST with Batch Correction (All Genes)",
pCutoff = 0.05,
FCcutoff = 1.0)

EnhancedVolcano(Malignant_CD4Tcells_vs_Normal_CD4Tcells,
lab = Malignant_CD4Tcells_vs_Normal_CD4Tcells$gene,
x = "avg_log2FC",
y = "p_val_adj",
selectLab = c('EPCAM', 'BCAT1', 'KIR3DL2', 'FOXM1', 'TWIST1', 'TNFSF9',
'CD80', 'IL1B', 'RPS4Y1',
'IL7R', 'TCF7', 'MKI67', 'CD70',
'IL2RA','TRBV6-2', 'TRBV10-3', 'TRBV4-2', 'TRBV9', 'TRBV7-9',
'TRAV12-1', 'CD8B', 'FCGR3A', 'GNLY', 'FOXP3', 'SELL',
'GIMAP1', 'RIPOR2', 'LEF1', 'HOXC9', 'SP5',
'CCL17', 'ETV4', 'THY1', 'FOXA2', 'ITGAD', 'S100P', 'TBX4',
'ID1', 'XCL1', 'SOX2', 'CD27', 'CD28','PLS3','CD70','RAB25' , 'TRBV27', 'TRBV2'),
title = "Malignant CD4 T cells(cell lines) vs normal CD4 T cells",
xlab = bquote(~Log[2]~ 'fold change'),
pCutoff = 0.05,
FCcutoff = 1.5,
pointSize = 3.0,
labSize = 5.0,
boxedLabels = TRUE,
colAlpha = 0.5,
legendPosition = 'right',
legendLabSize = 10,
legendIconSize = 4.0,
drawConnectors = TRUE,
widthConnectors = 0.5,
colConnectors = 'grey50',
arrowheads = FALSE,
max.overlaps = 30)

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_log2FC)))
# Create the EnhancedVolcano plot with the filtered data
EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0, filtered_genes$gene, NA),
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant CD4 T cells(cell lines) vs normal CD4 T cells",
pCutoff = 0.05,
FCcutoff = 1.0,
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_log2FC) >= 1.0] # Only label significant genes
)

EnhancedVolcano(
filtered_genes,
lab = ifelse(filtered_genes$p_val_adj <= 0.05 & abs(filtered_genes$avg_log2FC) >= 1.0, filtered_genes$gene, NA),
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant CD4 T cells (cell lines) vs Normal CD4 T cells",
subtitle = "Highlighting differentially expressed genes",
pCutoff = 0.05,
FCcutoff = 1.0,
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_log2FC) >= 1.0]
)

NA
NA
5. Create the Heatmap of fgsea results
library(pheatmap)
# Select the top 50 pathways
top_pathways <- fgsea_result %>%
arrange(padj) %>%
head(50)
# Create a matrix for the heatmap with pathways as rows and NES as the values
heatmap_data <- matrix(top_pathways$NES, nrow = length(top_pathways$pathway), ncol = 1)
rownames(heatmap_data) <- top_pathways$pathway
colnames(heatmap_data) <- c("NES")
# Plot the combined heatmap for the top 50 pathways
pheatmap(heatmap_data,
cluster_rows = TRUE,
cluster_cols = FALSE,
show_rownames = TRUE,
show_colnames = TRUE,
main = "Hallmark Pathways: Malignant CD4 T Cells compared to normal CD4 T cells",
color = colorRampPalette(c("blue", "white", "red"))(50))

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)
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgTWFsaWduYW50IENENFRjZWxscyB2cyBDb250cm9sKE5vcm1hbCBDRDQgVGNlbGxzKSIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjcm1kZm9ybWF0czo6cmVhZHRoZWRvd24KICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQpsaWJyYXJ5KFNldXJhdCkKbGlicmFyeShTZXVyYXRPYmplY3QpCmxpYnJhcnkoU2V1cmF0RGF0YSkKbGlicmFyeShwYXRjaHdvcmspCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkocmV0aWN1bGF0ZSkKbGlicmFyeShBemltdXRoKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KFJ0c25lKQpsaWJyYXJ5KGhhcm1vbnkpCmxpYnJhcnkoZ3JpZEV4dHJhKQpsaWJyYXJ5KEVuaGFuY2VkVm9sY2FubykKYGBgCgojIDIuIFBlcmZvcm0gREUgYW5hbHlzaXMgdXNpbmcgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIGdlbmVzCmBgYHtyIGRhdGExLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyA8LSByZWFkLmNzdigiMC1pbXBfUm9iai8xLU1BU1Rfd2l0aF9iYXRjaF9hc19Db3ZhcmlhdGVfd2l0aF9tZWFuRXhwcmVzc2lvbi5jc3YiLCBoZWFkZXIgPSBUKQpgYGAKCiMgMy4gQ3JlYXRlIHRoZSBFbmhhbmNlZFZvbGNhbm8gcGxvdApgYGB7ciBlbmhhbmNlZFYsIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD0xNn0KCkVuaGFuY2VkVm9sY2FubyhNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMsCiAgICAgICAgICAgICAgICBsYWIgPSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNQVNUIHdpdGggQmF0Y2ggQ29ycmVjdGlvbiAoQWxsIEdlbmVzKSIsCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMS4wKQoKCkVuaGFuY2VkVm9sY2FubyhNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGdlbmUsCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0VQQ0FNJywgJ0JDQVQxJywgJ0tJUjNETDInLCAnRk9YTTEnLCAnVFdJU1QxJywgJ1RORlNGOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnQ0Q4MCcsICAnSUwxQicsICdSUFM0WTEnLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0lMN1InLCAnVENGNycsICAnTUtJNjcnLCAnQ0Q3MCcsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnSUwyUkEnLCdUUkJWNi0yJywgJ1RSQlYxMC0zJywgJ1RSQlY0LTInLCAnVFJCVjknLCAnVFJCVjctOScsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnVFJBVjEyLTEnLCAnQ0Q4QicsICdGQ0dSM0EnLCAnR05MWScsICdGT1hQMycsICdTRUxMJywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdHSU1BUDEnLCAnUklQT1IyJywgJ0xFRjEnLCAnSE9YQzknLCAnU1A1JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ0NDTDE3JywgJ0VUVjQnLCAnVEhZMScsICdGT1hBMicsICdJVEdBRCcsICdTMTAwUCcsICdUQlg0JywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdJRDEnLCAnWENMMScsICdTT1gyJywgJ0NEMjcnLCAnQ0QyOCcsJ1BMUzMnLCdDRDcwJywnUkFCMjUnICwgJ1RSQlYyNycsICdUUkJWMicpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzKGNlbGwgbGluZXMpIHZzIG5vcm1hbCBDRDQgVCBjZWxscyIsCiAgICAgICAgICAgICAgICB4bGFiID0gYnF1b3RlKH5Mb2dbMl1+ICdmb2xkIGNoYW5nZScpLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEuNSwgCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNS4wLAogICAgICAgICAgICAgICAgYm94ZWRMYWJlbHMgPSBUUlVFLAogICAgICAgICAgICAgICAgY29sQWxwaGEgPSAwLjUsCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTAsCiAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuNSwKICAgICAgICAgICAgICAgIGNvbENvbm5lY3RvcnMgPSAnZ3JleTUwJywKICAgICAgICAgICAgICAgIGFycm93aGVhZHMgPSBGQUxTRSwKICAgICAgICAgICAgICAgIG1heC5vdmVybGFwcyA9IDMwKQoKCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgbmFtZWQgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzCiMgRmlsdGVyIGdlbmVzIGJhc2VkIG9uIGxvd2VzdCBwLXZhbHVlcyBidXQgaW5jbHVkZSBhbGwgZ2VuZXMKZmlsdGVyZWRfZ2VuZXMgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzICU+JQogIGFycmFuZ2UocF92YWxfYWRqLCBkZXNjKGFicyhhdmdfbG9nMkZDKSkpCgojIENyZWF0ZSB0aGUgRW5oYW5jZWRWb2xjYW5vIHBsb3Qgd2l0aCB0aGUgZmlsdGVyZWQgZGF0YQpFbmhhbmNlZFZvbGNhbm8oCiAgZmlsdGVyZWRfZ2VuZXMsIAogIGxhYiA9IGlmZWxzZShmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjAsIGZpbHRlcmVkX2dlbmVzJGdlbmUsIE5BKSwKICB4ID0gImF2Z19sb2cyRkMiLCAKICB5ID0gInBfdmFsX2FkaiIsCiAgdGl0bGUgPSAiTWFsaWduYW50IENENCBUIGNlbGxzKGNlbGwgbGluZXMpIHZzIG5vcm1hbCBDRDQgVCBjZWxscyIsCiAgcEN1dG9mZiA9IDAuMDUsCiAgRkNjdXRvZmYgPSAxLjAsCiAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLCAKICBsYWJDb2wgPSAnYmxhY2snLAogIGxhYkZhY2UgPSAnYm9sZCcsCiAgYm94ZWRMYWJlbHMgPSBGQUxTRSwgICMgU2V0IHRvIEZBTFNFIHRvIHJlbW92ZSBib3hlZCBsYWJlbHMKICBwb2ludFNpemUgPSAzLjAsCiAgbGFiU2l6ZSA9IDUuMCwKICBjb2wgPSBjKCdncmV5NzAnLCAnYmxhY2snLCAnYmx1ZScsICdyZWQnKSwgICMgQ3VzdG9taXplIHBvaW50IGNvbG9ycwogIHNlbGVjdExhYiA9IGZpbHRlcmVkX2dlbmVzJGdlbmVbZmlsdGVyZWRfZ2VuZXMkcF92YWxfYWRqIDw9IDAuMDUgJiBhYnMoZmlsdGVyZWRfZ2VuZXMkYXZnX2xvZzJGQykgPj0gMS4wXSAgIyBPbmx5IGxhYmVsIHNpZ25pZmljYW50IGdlbmVzCikKCgoKRW5oYW5jZWRWb2xjYW5vKAogIGZpbHRlcmVkX2dlbmVzLCAKICBsYWIgPSBpZmVsc2UoZmlsdGVyZWRfZ2VuZXMkcF92YWxfYWRqIDw9IDAuMDUgJiBhYnMoZmlsdGVyZWRfZ2VuZXMkYXZnX2xvZzJGQykgPj0gMS4wLCBmaWx0ZXJlZF9nZW5lcyRnZW5lLCBOQSksCiAgeCA9ICJhdmdfbG9nMkZDIiwgCiAgeSA9ICJwX3ZhbF9hZGoiLAogIHRpdGxlID0gIk1hbGlnbmFudCBDRDQgVCBjZWxscyAoY2VsbCBsaW5lcykgdnMgTm9ybWFsIENENCBUIGNlbGxzIiwKICBzdWJ0aXRsZSA9ICJIaWdobGlnaHRpbmcgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIiwKICBwQ3V0b2ZmID0gMC4wNSwKICBGQ2N1dG9mZiA9IDEuMCwKICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsCiAgY29sQWxwaGEgPSAwLjgsICAjIFNsaWdodCB0cmFuc3BhcmVuY3kgZm9yIG5vbi1zaWduaWZpY2FudCBwb2ludHMKICBjb2wgPSBjKCdncmV5NzAnLCAnYmxhY2snLCAnYmx1ZScsICdyZWQnKSwgICMgQ3VzdG9tIGNvbG9yIHNjaGVtZQogIGdyaWRsaW5lcy5tYWpvciA9IFRSVUUsCiAgZ3JpZGxpbmVzLm1pbm9yID0gRkFMU0UsCiAgc2VsZWN0TGFiID0gZmlsdGVyZWRfZ2VuZXMkZ2VuZVtmaWx0ZXJlZF9nZW5lcyRwX3ZhbF9hZGogPD0gMC4wNSAmIGFicyhmaWx0ZXJlZF9nZW5lcyRhdmdfbG9nMkZDKSA+PSAxLjBdCikgCgoKYGBgCgojIDQuICBQZXJmb3JtIEZhc3QgR1NFQSB1c2luZyBIYWxsbWFyayBHZW5lIFNldHMKYGBge3IgZGF0YTIsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKbGlicmFyeShmZ3NlYSkKbGlicmFyeShtc2lnZGJyKQpsaWJyYXJ5KGRwbHlyKQoKIyBPYnRhaW4gSGFsbG1hcmsgZ2VuZSBzZXRzIGZyb20gbXNpZ2RicgpoYWxsbWFya19nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiSCIpCgojIENvbnZlcnQgdGhlIGdlbmUgc2V0cyB0byBhIGxpc3QgZm9ybWF0IGZvciBmZ3NlYQpoYWxsbWFya19saXN0IDwtIGhhbGxtYXJrX2dlbmVzICU+JQogIHNwbGl0KHggPSAuJGdlbmVfc3ltYm9sLCBmID0gLiRnc19uYW1lKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgbmFtZWQgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3QgYmFzZWQgb24gYXZnX2xvZzJGQyBhbmQgcF92YWxfYWRqCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgJT4lCiAgbXV0YXRlKHJhbmtfbWV0cmljID0gYXZnX2xvZzJGQyAqIC1sb2cxMChwX3ZhbF9hZGopKQoKIyBFbnN1cmUgbm8gTkEgdmFsdWVzIGluIHJhbmtfbWV0cmljCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgJT4lCiAgZmlsdGVyKCFpcy5uYShyYW5rX21ldHJpYykpCgojIENyZWF0ZSBhIG5hbWVkIHZlY3RvciBmb3IgcmFua2luZwpnZW5lX2xpc3QgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJHJhbmtfbWV0cmljCm5hbWVzKGdlbmVfbGlzdCkgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGdlbmUKCiMgU29ydCB0aGUgbmFtZWQgdmVjdG9yIGluIGRlY3JlYXNpbmcgb3JkZXIKZ2VuZV9saXN0IDwtIHNvcnQoZ2VuZV9saXN0LCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgUGVyZm9ybSBmYXN0IEdTRUEKZmdzZWFfcmVzdWx0IDwtIGZnc2VhKHBhdGh3YXlzID0gaGFsbG1hcmtfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICBzdGF0cyA9IGdlbmVfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICBucGVybSA9IDEwMDApICAjIE51bWJlciBvZiBwZXJtdXRhdGlvbnMKCiMgVmlldyB0aGUgZmdzZWEgcmVzdWx0cwpoZWFkKGZnc2VhX3Jlc3VsdCkKCiMgUGxvdCB0aGUgdG9wIHBhdGh3YXkKdG9wX3BhdGh3YXkgPC0gZmdzZWFfcmVzdWx0W29yZGVyKGZnc2VhX3Jlc3VsdCRwYWRqKSwgXVsxLCBdCnBsb3RFbnJpY2htZW50KGhhbGxtYXJrX2xpc3RbW3RvcF9wYXRod2F5JHBhdGh3YXldXSwgZ2VuZV9saXN0KSArCiAgbGFicyh0aXRsZSA9IHRvcF9wYXRod2F5JHBhdGh3YXkpCgpgYGAKCiMgNS4gQ3JlYXRlIHRoZSBIZWF0bWFwIG9mIGZnc2VhIHJlc3VsdHMKYGBge3IgZGF0YTMsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KHBoZWF0bWFwKQoKIyBTZWxlY3QgdGhlIHRvcCA1MCBwYXRod2F5cwp0b3BfcGF0aHdheXMgPC0gZmdzZWFfcmVzdWx0ICU+JQogIGFycmFuZ2UocGFkaikgJT4lCiAgaGVhZCg1MCkKCiMgQ3JlYXRlIGEgbWF0cml4IGZvciB0aGUgaGVhdG1hcCB3aXRoIHBhdGh3YXlzIGFzIHJvd3MgYW5kIE5FUyBhcyB0aGUgdmFsdWVzCmhlYXRtYXBfZGF0YSA8LSBtYXRyaXgodG9wX3BhdGh3YXlzJE5FUywgbnJvdyA9IGxlbmd0aCh0b3BfcGF0aHdheXMkcGF0aHdheSksIG5jb2wgPSAxKQpyb3duYW1lcyhoZWF0bWFwX2RhdGEpIDwtIHRvcF9wYXRod2F5cyRwYXRod2F5CmNvbG5hbWVzKGhlYXRtYXBfZGF0YSkgPC0gYygiTkVTIikKCiMgUGxvdCB0aGUgY29tYmluZWQgaGVhdG1hcCBmb3IgdGhlIHRvcCA1MCBwYXRod2F5cwpwaGVhdG1hcChoZWF0bWFwX2RhdGEsIAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLCAKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsIAogICAgICAgICBzaG93X3Jvd25hbWVzID0gVFJVRSwgCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBUUlVFLAogICAgICAgICBtYWluID0gIkhhbGxtYXJrIFBhdGh3YXlzOiBNYWxpZ25hbnQgQ0Q0IFQgQ2VsbHMgY29tcGFyZWQgdG8gbm9ybWFsIENENCBUIGNlbGxzIiwKICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDUwKSkKCmBgYAoKIyA2LiBPYnRhaW4gS0VHRyBHZW5lIFNldHMgYW5kIFBlcmZvcm0gRmFzdCBHU0VBIFVzaW5nIEtFR0cgUGF0aHdheXMKYGBge3IgZGF0YTQsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQpsaWJyYXJ5KGZnc2VhKQpsaWJyYXJ5KG1zaWdkYnIpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkocGhlYXRtYXApCgojIE9idGFpbiBLRUdHIGdlbmUgc2V0cyBmcm9tIG1zaWdkYnIKa2VnZ19nZW5lcyA8LSBtc2lnZGJyKHNwZWNpZXMgPSAiSG9tbyBzYXBpZW5zIiwgY2F0ZWdvcnkgPSAiQzIiLCBzdWJjYXRlZ29yeSA9ICJDUDpLRUdHIikKCiMgQ29udmVydCB0aGUgZ2VuZSBzZXRzIHRvIGEgbGlzdCBmb3JtYXQgZm9yIGZnc2VhCmtlZ2dfbGlzdCA8LSBrZWdnX2dlbmVzICU+JQogIHNwbGl0KHggPSAuJGdlbmVfc3ltYm9sLCBmID0gLiRnc19uYW1lKQoKIyBBc3N1bWluZyB5b3UgaGF2ZSBhIGRhdGEgZnJhbWUgbmFtZWQgTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3QgYmFzZWQgb24gYXZnX2xvZzJGQyBhbmQgcF92YWxfYWRqCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgJT4lCiAgbXV0YXRlKHJhbmtfbWV0cmljID0gYXZnX2xvZzJGQyAqIC1sb2cxMChwX3ZhbF9hZGopKQoKIyBFbnN1cmUgbm8gTkEgdmFsdWVzIGluIHJhbmtfbWV0cmljCk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMgJT4lCiAgZmlsdGVyKCFpcy5uYShyYW5rX21ldHJpYykpCgojIENyZWF0ZSBhIG5hbWVkIHZlY3RvciBmb3IgcmFua2luZwpnZW5lX2xpc3QgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJHJhbmtfbWV0cmljCm5hbWVzKGdlbmVfbGlzdCkgPC0gTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzJGdlbmUKCiMgU29ydCB0aGUgbmFtZWQgdmVjdG9yIGluIGRlY3JlYXNpbmcgb3JkZXIKZ2VuZV9saXN0IDwtIHNvcnQoZ2VuZV9saXN0LCBkZWNyZWFzaW5nID0gVFJVRSkKCiMgUGVyZm9ybSBmYXN0IEdTRUEgdXNpbmcgS0VHRyBwYXRod2F5cwpmZ3NlYV9yZXN1bHRfa2VnZyA8LSBmZ3NlYShwYXRod2F5cyA9IGtlZ2dfbGlzdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXRzID0gZ2VuZV9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgbnBlcm0gPSAxMDAwKSAgIyBOdW1iZXIgb2YgcGVybXV0YXRpb25zCgojIFZpZXcgdGhlIGZnc2VhIHJlc3VsdHMKaGVhZChmZ3NlYV9yZXN1bHRfa2VnZykKCiMgU2VwYXJhdGUgdXByZWd1bGF0ZWQgKHBvc2l0aXZlIE5FUykgYW5kIGRvd25yZWd1bGF0ZWQgKG5lZ2F0aXZlIE5FUykgcGF0aHdheXMKdXByZWd1bGF0ZWRfcGF0aHdheXMgPC0gZmdzZWFfcmVzdWx0X2tlZ2cgJT4lIGZpbHRlcihORVMgPiAwKSAlPiUgYXJyYW5nZShwYWRqKSAlPiUgaGVhZCgyMCkKZG93bnJlZ3VsYXRlZF9wYXRod2F5cyA8LSBmZ3NlYV9yZXN1bHRfa2VnZyAlPiUgZmlsdGVyKE5FUyA8IDApICU+JSBhcnJhbmdlKHBhZGopICU+JSBoZWFkKDIwKQoKIyBDb21iaW5lIHRoZSB0b3AgMjAgdXByZWd1bGF0ZWQgYW5kIHRvcCAyMCBkb3ducmVndWxhdGVkIHBhdGh3YXlzCmNvbWJpbmVkX3BhdGh3YXlzIDwtIGJpbmRfcm93cyh1cHJlZ3VsYXRlZF9wYXRod2F5cywgZG93bnJlZ3VsYXRlZF9wYXRod2F5cykKCiMgQ3JlYXRlIGEgbWF0cml4IGZvciB0aGUgaGVhdG1hcCB3aXRoIHBhdGh3YXlzIGFzIHJvd3MgYW5kIE5FUyBhcyB0aGUgdmFsdWVzCmhlYXRtYXBfZGF0YV9jb21iaW5lZCA8LSBtYXRyaXgoY29tYmluZWRfcGF0aHdheXMkTkVTLCBucm93ID0gbGVuZ3RoKGNvbWJpbmVkX3BhdGh3YXlzJHBhdGh3YXkpLCBuY29sID0gMSkKcm93bmFtZXMoaGVhdG1hcF9kYXRhX2NvbWJpbmVkKSA8LSBjb21iaW5lZF9wYXRod2F5cyRwYXRod2F5CmNvbG5hbWVzKGhlYXRtYXBfZGF0YV9jb21iaW5lZCkgPC0gYygiTkVTIikKCiMgUGxvdCB0aGUgY29tYmluZWQgaGVhdG1hcCBmb3IgdGhlIHRvcCAyMCB1cHJlZ3VsYXRlZCBhbmQgdG9wIDIwIGRvd25yZWd1bGF0ZWQgcGF0aHdheXMKcGhlYXRtYXAoaGVhdG1hcF9kYXRhX2NvbWJpbmVkLCAKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gVFJVRSwgCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAKICAgICAgICAgc2hvd19yb3duYW1lcyA9IFRSVUUsIAogICAgICAgICBzaG93X2NvbG5hbWVzID0gVFJVRSwKICAgICAgICAgbWFpbiA9ICJLRUdHIFBhdGh3YXlzOiBNYWxpZ25hbnQgQ0Q0IFQgQ2VsbHMgY29tcGFyZWQgdG8gbm9ybWFsIENENCBUIENlbGxzIiwKICAgICAgICAgY29sb3IgPSBjb2xvclJhbXBQYWxldHRlKGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpKDUwKSkKYGBgCgojIDYuIE9idGFpbiBLRUdHIEdlbmUgU2V0cyBhbmQgUGVyZm9ybSBGYXN0IEdTRUEgVXNpbmcgS0VHRyBQYXRod2F5cwpgYGB7ciBkYXRhNSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZmdzZWEpCmxpYnJhcnkobXNpZ2RicikKbGlicmFyeShkcGx5cikKbGlicmFyeShwaGVhdG1hcCkKCiMgT2J0YWluIEtFR0cgZ2VuZSBzZXRzIGZyb20gbXNpZ2RicgprZWdnX2dlbmVzIDwtIG1zaWdkYnIoc3BlY2llcyA9ICJIb21vIHNhcGllbnMiLCBjYXRlZ29yeSA9ICJDMiIsIHN1YmNhdGVnb3J5ID0gIkNQOktFR0ciKQoKIyBDb252ZXJ0IHRoZSBnZW5lIHNldHMgdG8gYSBsaXN0IGZvcm1hdCBmb3IgZmdzZWEKa2VnZ19saXN0IDwtIGtlZ2dfZ2VuZXMgJT4lCiAgc3BsaXQoeCA9IC4kZ2VuZV9zeW1ib2wsIGYgPSAuJGdzX25hbWUpCgojIEFzc3VtaW5nIHlvdSBoYXZlIGEgZGF0YSBmcmFtZSBuYW1lZCBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMKIyBDcmVhdGUgYSByYW5rZWQgbGlzdCBiYXNlZCBvbiBhdmdfbG9nMkZDIGFuZCBwX3ZhbF9hZGoKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBtdXRhdGUocmFua19tZXRyaWMgPSBhdmdfbG9nMkZDICogLWxvZzEwKHBfdmFsX2FkaikpCgojIEVuc3VyZSBubyBOQSB2YWx1ZXMgaW4gcmFua19tZXRyaWMKTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzIDwtIE1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxscyAlPiUKICBmaWx0ZXIoIWlzLm5hKHJhbmtfbWV0cmljKSkKCiMgQ3JlYXRlIGEgbmFtZWQgdmVjdG9yIGZvciByYW5raW5nCmdlbmVfbGlzdCA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkcmFua19tZXRyaWMKbmFtZXMoZ2VuZV9saXN0KSA8LSBNYWxpZ25hbnRfQ0Q0VGNlbGxzX3ZzX05vcm1hbF9DRDRUY2VsbHMkZ2VuZQoKIyBTb3J0IHRoZSBuYW1lZCB2ZWN0b3IgaW4gZGVjcmVhc2luZyBvcmRlcgpnZW5lX2xpc3QgPC0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBQZXJmb3JtIGZhc3QgR1NFQSB1c2luZyBLRUdHIHBhdGh3YXlzCmZnc2VhX3Jlc3VsdF9rZWdnIDwtIGZnc2VhKHBhdGh3YXlzID0ga2VnZ19saXN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhdHMgPSBnZW5lX2xpc3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICBucGVybSA9IDEwMDApICAjIE51bWJlciBvZiBwZXJtdXRhdGlvbnMKCiMgVmlldyB0aGUgZmdzZWEgcmVzdWx0cwpoZWFkKGZnc2VhX3Jlc3VsdF9rZWdnKQoKIyBTZXBhcmF0ZSB1cHJlZ3VsYXRlZCAocG9zaXRpdmUgTkVTKSBhbmQgZG93bnJlZ3VsYXRlZCAobmVnYXRpdmUgTkVTKSBwYXRod2F5cwp1cHJlZ3VsYXRlZF9wYXRod2F5cyA8LSBmZ3NlYV9yZXN1bHRfa2VnZyAlPiUgZmlsdGVyKE5FUyA+IDApICU+JSBhcnJhbmdlKHBhZGopICU+JSBoZWFkKDUpCmRvd25yZWd1bGF0ZWRfcGF0aHdheXMgPC0gZmdzZWFfcmVzdWx0X2tlZ2cgJT4lIGZpbHRlcihORVMgPCAwKSAlPiUgYXJyYW5nZShwYWRqKSAlPiUgaGVhZCg1KQoKIyBDb21iaW5lIHRoZSB0b3AgNSB1cHJlZ3VsYXRlZCBhbmQgdG9wIDUgZG93bnJlZ3VsYXRlZCBwYXRod2F5cwpjb21iaW5lZF9wYXRod2F5cyA8LSBiaW5kX3Jvd3ModXByZWd1bGF0ZWRfcGF0aHdheXMsIGRvd25yZWd1bGF0ZWRfcGF0aHdheXMpCgojIENyZWF0ZSBhIG1hdHJpeCBmb3IgdGhlIGhlYXRtYXAgd2l0aCBwYXRod2F5cyBhcyByb3dzIGFuZCBORVMgYXMgdGhlIHZhbHVlcwpoZWF0bWFwX2RhdGFfY29tYmluZWQgPC0gbWF0cml4KGNvbWJpbmVkX3BhdGh3YXlzJE5FUywgbnJvdyA9IGxlbmd0aChjb21iaW5lZF9wYXRod2F5cyRwYXRod2F5KSwgbmNvbCA9IDEpCnJvd25hbWVzKGhlYXRtYXBfZGF0YV9jb21iaW5lZCkgPC0gY29tYmluZWRfcGF0aHdheXMkcGF0aHdheQpjb2xuYW1lcyhoZWF0bWFwX2RhdGFfY29tYmluZWQpIDwtIGMoIk5FUyIpCgojIFBsb3QgdGhlIGNvbWJpbmVkIGhlYXRtYXAgZm9yIHRoZSB0b3AgMjAgdXByZWd1bGF0ZWQgYW5kIHRvcCAyMCBkb3ducmVndWxhdGVkIHBhdGh3YXlzCnBoZWF0bWFwKGhlYXRtYXBfZGF0YV9jb21iaW5lZCwgCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsIAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgICAgICAgIHNob3dfcm93bmFtZXMgPSBUUlVFLCAKICAgICAgICAgc2hvd19jb2xuYW1lcyA9IFRSVUUsCiAgICAgICAgIG1haW4gPSAiS0VHRyBQYXRod2F5czogTWFsaWduYW50IENENCBUIENlbGxzIGNvbXBhcmVkIHRvIG5vcm1hbCBDRDQgVCBDZWxscyIsCiAgICAgICAgIGNvbG9yID0gY29sb3JSYW1wUGFsZXR0ZShjKCJibHVlIiwgIndoaXRlIiwgInJlZCIpKSg1MCkpCmBgYAojIDcuIFNhdmUgSGFsbG1hcmsgYW5kIGtlZ2cgdG8gQ1NWCmBgYHtyIGRhdGE2LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgQXNzdW1pbmcgeW91IGhhdmUgdGhlIHJlc3VsdHMgc3RvcmVkIGluIGZnc2VhX3Jlc3VsdF9oYWxsbWFyayBhbmQgZmdzZWFfcmVzdWx0X2tlZ2cKCiMgRmxhdHRlbiB0aGUgbGlzdCBjb2x1bW5zIGludG8gY2hhcmFjdGVyIHN0cmluZ3MgZm9yIEhhbGxtYXJrIHJlc3VsdHMKZmdzZWFfcmVzdWx0X2hhbGxtYXJrX2ZsYXR0ZW5lZCA8LSBmZ3NlYV9yZXN1bHQgJT4lCiAgbXV0YXRlKGFjcm9zcyh3aGVyZShpcy5saXN0KSwgfiBzYXBwbHkoLiwgdG9TdHJpbmcpKSkKCiMgV3JpdGUgdGhlIGZsYXR0ZW5lZCBIYWxsbWFyayByZXN1bHRzIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KGZnc2VhX3Jlc3VsdF9oYWxsbWFya19mbGF0dGVuZWQsICJmZ3NlYV9yZXN1bHRzX2hhbGxtYXJrLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyBGbGF0dGVuIHRoZSBsaXN0IGNvbHVtbnMgaW50byBjaGFyYWN0ZXIgc3RyaW5ncyBmb3IgS0VHRyByZXN1bHRzCmZnc2VhX3Jlc3VsdF9rZWdnX2ZsYXR0ZW5lZCA8LSBmZ3NlYV9yZXN1bHRfa2VnZyAlPiUKICBtdXRhdGUoYWNyb3NzKHdoZXJlKGlzLmxpc3QpLCB+IHNhcHBseSguLCB0b1N0cmluZykpKQoKIyBXcml0ZSB0aGUgZmxhdHRlbmVkIEtFR0cgcmVzdWx0cyB0byBhIENTViBmaWxlCndyaXRlLmNzdihmZ3NlYV9yZXN1bHRfa2VnZ19mbGF0dGVuZWQsICJmZ3NlYV9yZXN1bHRzX2tlZ2cuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKCmBgYAo=