1. load libraries

2. load seurat object

#Load Seurat Object
load("/home/nabbasi/isilon/To_Transfer_between_computers/23-Harmony_Integration/0-robj/5-Harmony_Integrated_All_samples_Merged_CD4Tcells_final_Resolution_Selected_0.8_ADT_Normalized_cleaned_mt.robj")



Layers(All_samples_Merged@assays$RNA)
[1] "data"   "counts"

3. clusters vs the rest

markers_genes %>%
    group_by(cluster) %>%
    dplyr::filter(avg_log2FC > 1) %>%
    slice_head(n = 5) %>%
    ungroup() -> top5
DoHeatmap(All_samples_Merged, features = top5$gene) + NoLegend()
Avis : Layer ‘scale.data’ is emptyErreur dans DoHeatmap(All_samples_Merged, features = top5$gene) : 
  No requested features found in the scale.data slot for the RNA assay.

4. top 25 overexpressed genes for plotting.

# Same plotting commands
P1 <- par(mfrow = c(2, 5), mar = c(4, 6, 3, 1))
for (i in unique(top25$cluster)) {
    barplot(sort(setNames(top25$avg_log2FC, top25$gene)[top25$cluster == i], F),
        horiz = T, las = 1, main = paste0(i, " vs. rest"), border = "white", yaxs = "i"
    )
    abline(v = c(0, 0.25), lty = c(1, 2))
}



P1
$mfrow
[1] 1 1

$mar
[1] 5.1 4.1 2.1 2.1

5. top 5 overexpressed genes for plotting heatmap

#alldata <- All_samples_Merged

# create a scale.data slot for the selected genes
alldata <- ScaleData(alldata, features = as.character(unique(top5$gene)), assay = "RNA")
Centering and scaling data matrix

  |                                                                                        
  |                                                                                  |   0%
  |                                                                                        
  |==================================================================================| 100%
heatmap_plot <- DoHeatmap(alldata, features = as.character(unique(top5$gene)), group.by = "seurat_clusters", assay = "RNA", size = 2.5)

# Save the heatmap as a PNG image (with 300 dpi for high-quality publication)
ggsave("top5_marker_genes_heatmap.png", plot = heatmap_plot, width = 12, height = 8, dpi = 300)

heatmap_plot

6. top 5 overexpressed genes for plotting dotplot

#alldata <- All_samples_Merged
  
DotPlot(alldata, features = rev(as.character(unique(top5$gene))), group.by = "seurat_clusters", assay = "RNA") + coord_flip()

7. scPubr Group-Wise DE analysis Plot


# library(SCpubr)
# 
# p1 <- SCpubr::do_GroupwiseDEPlot(sample = alldata,
#                                 de_genes = markers_genes,
#                                 min.cutoff = 1)
# 
# p1
# 
# p2 <- SCpubr::do_GroupwiseDEPlot(sample = alldata,
#                                 de_genes = markers_genes,
#                                 top_genes = 5)
# 
# p2
# 
# p3 <- SCpubr::do_GroupwiseDEPlot(sample = alldata,
#                                 de_genes = markers_genes,
#                                 group.by = c("seurat_clusters", 
#                                              "cell_line", 
#                                              "Patient_origin"),
#                                 row_title_expression = c("",
#                                                          "cell_line",
#                                                          "Donor"))
#       
# 
# p3

8. scPubr Group-Wise DE analysis Plot


library(scCustomize)
scCustomize v3.0.1
If you find the scCustomize useful please cite.
See 'samuel-marsh.github.io/scCustomize/articles/FAQ.html' for citation info.
top5 <- top5[!duplicated(top5$gene), ]

p4 <- DotPlot_scCustom(seurat_object = All_samples_Merged, features = top5$gene, x_lab_rotate = TRUE)

p4

p5 <- DotPlot_scCustom(seurat_object = All_samples_Merged, features = top5$gene, flip_axes = T,
    remove_axis_titles = FALSE)

p5

p6 <- Clustered_DotPlot(seurat_object = All_samples_Merged, features = top5$gene, k = 8)
                                

p6
[[1]]

[[2]]

7. scPubr Group-Wise DE analysis Plot

library(SCpubr)

# Create a named list of genes for each cluster
genes <- split(top5$gene, top5$cluster)

# Generate the dot plot
p <- SCpubr::do_DotPlot(
    sample = All_samples_Merged,  # Replace with your Seurat object
    features = genes,flip = TRUE
)
Erreur : Please provide the genes as a simple character vector or set flip to FALSE.

top 5 overexpressed genes for plotting heatmap


#alldata <- All_samples_Merged

library(dplyr)

# Select the top 5 genes per cluster, ensuring unique genes across clusters
top5_U <- markers_genes %>%
    arrange(p_val_adj, desc(avg_log2FC)) %>%  # Sort by p_val_adj (ascending) and avg_log2FC (descending)
    distinct(gene, .keep_all = TRUE) %>%      # Remove duplicate genes across clusters
    group_by(cluster) %>%
    top_n(-5, p_val_adj) %>%                  # Select the top 5 genes by p_val_adj
    top_n(5, avg_log2FC) %>%                  # Further select the top 5 genes by avg_log2FC
    ungroup()

# Order genes by cluster
ordered_genes <- top5_U %>%
    arrange(cluster) %>%  # Sort by cluster
    pull(gene)            # Extract the ordered gene names as a vector

# Scale data for the selected genes
alldata <- ScaleData(alldata, features = as.character(ordered_genes), assay = "RNA")

# Create the heatmap with ordered genes
heatmap_plot <- DoHeatmap(
    alldata,
    features = as.character(ordered_genes),  # Use the ordered genes
    group.by = "seurat_clusters",
    assay = "RNA",
    size = 2.5
)

# Save the heatmap as a PNG image (with 300 dpi for high-quality publication)
ggsave("top5_U_marker_genes_heatmap.png", plot = heatmap_plot, width = 12, height = 8, dpi = 300)

top 5 overexpressed genes for plotting dotplot

# alldata <- All_samples_Merged
#   
# DotPlot(alldata, features = rev(as.character(unique(top5_U$gene))), group.by = "seurat_clusters", assay = "RNA") + coord_flip()
# 
# # Save marker genes to a CSV file
# #write.csv(top25, file = "Top25_markers_genes_RNA_Wilcox.csv", row.names = TRUE)
# 
# 
# # Save marker genes to a CSV file
# write.csv(top5_U, file = "top5_U_markers_genes_RNA_Wilcox.csv", row.names = TRUE)

library(dplyr)

# Order genes by cluster
ordered_genes <- top5_U %>%
    arrange(cluster) %>%  # Sort by cluster
    pull(gene)            # Extract the ordered gene names as a vector

# Create the DotPlot with ordered genes
dotplot <- DotPlot(
    alldata,
    features = rev(as.character(ordered_genes)),  # Reverse the order for coord_flip()
    group.by = "seurat_clusters",
    assay = "RNA"
) + coord_flip()

# Display the DotPlot
print(dotplot)

# Save the DotPlot as a high-resolution image
ggsave("top5_U_marker_genes_dotplot.png", plot = dotplot, width = 12, height = 8, dpi = 300)

# Save the ordered marker genes to a CSV file
write.csv(top5_U %>% arrange(cluster), file = "top5_U_markers_genes_RNA_Wilcox.csv", row.names = TRUE)

scPubr Group-Wise DE analysis Plot


library(scCustomize)

top5_U <- top5_U[!duplicated(top5_U$gene), ]

p4 <- DotPlot_scCustom(seurat_object = All_samples_Merged, features = ordered_genes, x_lab_rotate = TRUE)

p4

p5 <- DotPlot_scCustom(seurat_object = All_samples_Merged, features = ordered_genes, flip_axes = T,
    remove_axis_titles = FALSE)

p5

p6 <- Clustered_DotPlot(seurat_object = All_samples_Merged, features = ordered_genes, k = 8)
                                

p6

scPubr Group-Wise DE analysis Plot


library(SCpubr)

# Create a named list of genes for each cluster
#genes <- split(top5_U$gene, top5_U$cluster)

# Generate the dot plot
p <- SCpubr::do_DotPlot(
    sample = All_samples_Merged,  # Replace with your Seurat object
    features = ordered_genes
)

# Print the plot
print(p)

ggsave("top5_U_Genes_Per_Cluster_DotPlot.png", plot = p, width = 12, height = 8, dpi = 300)
LS0tCnRpdGxlOiAiV2lsY294IEFuYWx5c2lzIFJOQSBUb3AgTWFya2VycyIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICAgIGxpYnJhcnkoU2V1cmF0KQogICAgbGlicmFyeShkcGx5cikKICAgIGxpYnJhcnkocGF0Y2h3b3JrKQogICAgbGlicmFyeShnZ3Bsb3QyKQogICAgbGlicmFyeShwaGVhdG1hcCkKICAgIGxpYnJhcnkoZW5yaWNoUikKICAgIGxpYnJhcnkoTWF0cml4KQogICAgbGlicmFyeShlZGdlUikKfSkKCmBgYAoKCiMgMi4gbG9hZCBzZXVyYXQgb2JqZWN0CmBgYHtyIGxvYWRfc2V1cmF0fQojTG9hZCBTZXVyYXQgT2JqZWN0CmxvYWQoIi9ob21lL25hYmJhc2kvaXNpbG9uL1RvX1RyYW5zZmVyX2JldHdlZW5fY29tcHV0ZXJzLzIzLUhhcm1vbnlfSW50ZWdyYXRpb24vMC1yb2JqLzUtSGFybW9ueV9JbnRlZ3JhdGVkX0FsbF9zYW1wbGVzX01lcmdlZF9DRDRUY2VsbHNfZmluYWxfUmVzb2x1dGlvbl9TZWxlY3RlZF8wLjhfQURUX05vcm1hbGl6ZWRfY2xlYW5lZF9tdC5yb2JqIikKCgoKTGF5ZXJzKEFsbF9zYW1wbGVzX01lcmdlZEBhc3NheXMkUk5BKQoKCgoKCmBgYAoKIyAzLiBjbHVzdGVycyB2cyB0aGUgcmVzdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCkRlZmF1bHRBc3NheShBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJSTkEiCgojIE5vcm1hbGl6ZSB0aGUgUk5BIGFzc2F5CkFsbF9zYW1wbGVzX01lcmdlZCA8LSBOb3JtYWxpemVEYXRhKEFsbF9zYW1wbGVzX01lcmdlZCwgYXNzYXkgPSAiUk5BIiwgbm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDApCgoKIyBDb21wdXRlIGRpZmZlcmVudGlhbCBleHByZXNzaW9uCm1hcmtlcnNfZ2VuZXMgPC0gRmluZEFsbE1hcmtlcnMoCiAgICBBbGxfc2FtcGxlc19NZXJnZWQsCiAgICB0ZXN0LnVzZSA9ICJ3aWxjb3giLAogICAgbG9nZmMudGhyZXNob2xkID0gMC4xLAogICAgbWluLnBjdCA9IDAuMSwKICAgIHJldHVybi50aHJlc2ggPSAxZS01LAogICAgb25seS5wb3MgPSBUUlVFLAogICAgYXNzYXkgPSAiUk5BIgopCgoKIyBPcHRpb25hbDogYWRkIGEgc3BlY2lmaWNpdHkgc2NvcmUgKGZvciBzb3J0aW5nIGxhdGVyKQptYXJrZXJzX2FsbCA8LSBtYXJrZXJzX2dlbmVzICU+JQogIG11dGF0ZShzcGVjaWZpY2l0eV9zY29yZSA9IGF2Z19sb2cyRkMgKiAocGN0LjEgLSBwY3QuMikpCgojIEdldCB0b3AgNSBtYXJrZXJzIHBlciBjbHVzdGVyIHVzaW5nIHNwZWNpZmljaXR5IG9yIGF2Z19sb2cyRkMKdG9wNSA8LSBtYXJrZXJzX2FsbCAlPiUKICBncm91cF9ieShjbHVzdGVyKSAlPiUKICBzbGljZV9tYXgob3JkZXJfYnkgPSBzcGVjaWZpY2l0eV9zY29yZSwgbiA9IDUsIHdpdGhfdGllcyA9IEZBTFNFKQoKCiMgR2V0IHRvcCAxMCBtYXJrZXJzIHBlciBjbHVzdGVyIHVzaW5nIHNwZWNpZmljaXR5IG9yIGF2Z19sb2cyRkMKdG9wMTAgPC0gbWFya2Vyc19hbGwgJT4lCiAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gc3BlY2lmaWNpdHlfc2NvcmUsIG4gPSAxMCwgd2l0aF90aWVzID0gRkFMU0UpCgojIEdldCB0b3AgMjUgbWFya2VycyBwZXIgY2x1c3RlciB1c2luZyBzcGVjaWZpY2l0eSBvciBhdmdfbG9nMkZDCnRvcDI1IDwtIG1hcmtlcnNfYWxsICU+JQogIGdyb3VwX2J5KGNsdXN0ZXIpICU+JQogIHNsaWNlX21heChvcmRlcl9ieSA9IHNwZWNpZmljaXR5X3Njb3JlLCBuID0gMjUsIHdpdGhfdGllcyA9IEZBTFNFKQoKCiMgU2F2ZQp3cml0ZS5jc3YodG9wNSwgIlRvcDVfbWFya2Vyc19wZXJfY2x1c3Rlci5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KHRvcDEwLCAiVG9wMTBfbWFya2Vyc19wZXJfY2x1c3Rlci5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KHRvcDI1LCAiVG9wMjVfbWFya2Vyc19wZXJfY2x1c3Rlci5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KG1hcmtlcnNfZ2VuZXMsICJBbGxfbWFya2VyX2dlbmVzX1JOQV9XaWxjb3guY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFNhdmUgbWFya2VyIGdlbmVzIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KG1hcmtlcnNfZ2VuZXMsIGZpbGUgPSAiVG9wX21hcmtlcnNfZ2VuZXNfUk5BX1dpbGNveF93aXRoX3Jvd25hbWVzLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCgpgYGAKCgoKIyA0LiB0b3AgMjUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcuCmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQoKCiMgU2F2ZSB0byBQREYgd2l0aCBoaWdoIHJlc29sdXRpb24KcGRmKCJUb3AyNV9NYXJrZXJzX0JhcnBsb3RzLnBkZiIsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgpCgojIFNldCB1cCBtdWx0aS1wYW5lbCBsYXlvdXQgYW5kIG1hcmdpbnMKcGFyKG1mcm93ID0gYygyLCA1KSwgbWFyID0gYyg0LCA2LCAzLCAxKSkKCiMgTG9vcCBvdmVyIGNsdXN0ZXJzCmZvciAoaSBpbiB1bmlxdWUodG9wMjUkY2x1c3RlcikpIHsKICAgIGJhcnBsb3Qoc29ydChzZXROYW1lcyh0b3AyNSRhdmdfbG9nMkZDLCB0b3AyNSRnZW5lKVt0b3AyNSRjbHVzdGVyID09IGldLCBGKSwKICAgICAgICBob3JpeiA9IFQsIGxhcyA9IDEsIG1haW4gPSBwYXN0ZTAoaSwgIiB2cy4gcmVzdCIpLCBib3JkZXIgPSAid2hpdGUiLCB5YXhzID0gImkiCiAgICApCiAgICBhYmxpbmUodiA9IGMoMCwgMC4yNSksIGx0eSA9IGMoMSwgMikpCn0KIyBDbG9zZSB0aGUgUERGIGRldmljZQpkZXYub2ZmKCkKCgojIFNhbWUgcGxvdHRpbmcgY29tbWFuZHMKUDEgPC0gcGFyKG1mcm93ID0gYygyLCA1KSwgbWFyID0gYyg0LCA2LCAzLCAxKSkKZm9yIChpIGluIHVuaXF1ZSh0b3AyNSRjbHVzdGVyKSkgewogICAgYmFycGxvdChzb3J0KHNldE5hbWVzKHRvcDI1JGF2Z19sb2cyRkMsIHRvcDI1JGdlbmUpW3RvcDI1JGNsdXN0ZXIgPT0gaV0sIEYpLAogICAgICAgIGhvcml6ID0gVCwgbGFzID0gMSwgbWFpbiA9IHBhc3RlMChpLCAiIHZzLiByZXN0IiksIGJvcmRlciA9ICJ3aGl0ZSIsIHlheHMgPSAiaSIKICAgICkKICAgIGFibGluZSh2ID0gYygwLCAwLjI1KSwgbHR5ID0gYygxLCAyKSkKfQoKClAxCgoKYGBgCgoKCiMgNS4gdG9wIDUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcgaGVhdG1hcApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KI2FsbGRhdGEgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkCgojIGNyZWF0ZSBhIHNjYWxlLmRhdGEgc2xvdCBmb3IgdGhlIHNlbGVjdGVkIGdlbmVzCmFsbGRhdGEgPC0gU2NhbGVEYXRhKGFsbGRhdGEsIGZlYXR1cmVzID0gYXMuY2hhcmFjdGVyKHVuaXF1ZSh0b3A1JGdlbmUpKSwgYXNzYXkgPSAiUk5BIikKaGVhdG1hcF9wbG90IDwtIERvSGVhdG1hcChhbGxkYXRhLCBmZWF0dXJlcyA9IGFzLmNoYXJhY3Rlcih1bmlxdWUodG9wNSRnZW5lKSksIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGFzc2F5ID0gIlJOQSIsIHNpemUgPSAyLjUpCgojIFNhdmUgdGhlIGhlYXRtYXAgYXMgYSBQTkcgaW1hZ2UgKHdpdGggMzAwIGRwaSBmb3IgaGlnaC1xdWFsaXR5IHB1YmxpY2F0aW9uKQpnZ3NhdmUoInRvcDVfbWFya2VyX2dlbmVzX2hlYXRtYXAucG5nIiwgcGxvdCA9IGhlYXRtYXBfcGxvdCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gOCwgZHBpID0gMzAwKQoKaGVhdG1hcF9wbG90CmBgYAoKCiMgNi4gdG9wIDUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcgZG90cGxvdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KI2FsbGRhdGEgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkCiAgCkRvdFBsb3QoYWxsZGF0YSwgZmVhdHVyZXMgPSByZXYoYXMuY2hhcmFjdGVyKHVuaXF1ZSh0b3A1JGdlbmUpKSksIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGFzc2F5ID0gIlJOQSIpICsgY29vcmRfZmxpcCgpCgpgYGAKCiMgNy4gc2NQdWJyIEdyb3VwLVdpc2UgREUgYW5hbHlzaXMgUGxvdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCiMgbGlicmFyeShTQ3B1YnIpCiMgCiMgcDEgPC0gU0NwdWJyOjpkb19Hcm91cHdpc2VERVBsb3Qoc2FtcGxlID0gYWxsZGF0YSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX2dlbmVzID0gbWFya2Vyc19nZW5lcywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5jdXRvZmYgPSAxKQojIAojIHAxCiMgCiMgcDIgPC0gU0NwdWJyOjpkb19Hcm91cHdpc2VERVBsb3Qoc2FtcGxlID0gYWxsZGF0YSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX2dlbmVzID0gbWFya2Vyc19nZW5lcywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcF9nZW5lcyA9IDUpCiMgCiMgcDIKIyAKIyBwMyA8LSBTQ3B1YnI6OmRvX0dyb3Vwd2lzZURFUGxvdChzYW1wbGUgPSBhbGxkYXRhLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVfZ2VuZXMgPSBtYXJrZXJzX2dlbmVzLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JvdXAuYnkgPSBjKCJzZXVyYXRfY2x1c3RlcnMiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiY2VsbF9saW5lIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlBhdGllbnRfb3JpZ2luIiksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3dfdGl0bGVfZXhwcmVzc2lvbiA9IGMoIiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNlbGxfbGluZSIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRvbm9yIikpCiMgICAgICAgCiMgCiMgcDMKCmBgYAoKCiMgOC4gc2NQdWJyIEdyb3VwLVdpc2UgREUgYW5hbHlzaXMgUGxvdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCmxpYnJhcnkoc2NDdXN0b21pemUpCgp0b3A1IDwtIHRvcDVbIWR1cGxpY2F0ZWQodG9wNSRnZW5lKSwgXQoKcDQgPC0gRG90UGxvdF9zY0N1c3RvbShzZXVyYXRfb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCBmZWF0dXJlcyA9IHRvcDUkZ2VuZSwgeF9sYWJfcm90YXRlID0gVFJVRSkKCnA0CgpwNSA8LSBEb3RQbG90X3NjQ3VzdG9tKHNldXJhdF9vYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gdG9wNSRnZW5lLCBmbGlwX2F4ZXMgPSBULAogICAgcmVtb3ZlX2F4aXNfdGl0bGVzID0gRkFMU0UpCgpwNQoKcDYgPC0gQ2x1c3RlcmVkX0RvdFBsb3Qoc2V1cmF0X29iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSB0b3A1JGdlbmUsIGsgPSA4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKcDYKCmBgYAojIDcuIHNjUHViciBHcm91cC1XaXNlIERFIGFuYWx5c2lzIFBsb3QKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CgpsaWJyYXJ5KFNDcHVicikKCiMgQ3JlYXRlIGEgbmFtZWQgbGlzdCBvZiBnZW5lcyBmb3IgZWFjaCBjbHVzdGVyCmdlbmVzIDwtIHNwbGl0KHRvcDUkZ2VuZSwgdG9wNSRjbHVzdGVyKQoKIyBHZW5lcmF0ZSB0aGUgZG90IHBsb3QKcCA8LSBTQ3B1YnI6OmRvX0RvdFBsb3QoCiAgICBzYW1wbGUgPSBBbGxfc2FtcGxlc19NZXJnZWQsICAjIFJlcGxhY2Ugd2l0aCB5b3VyIFNldXJhdCBvYmplY3QKICAgIGZlYXR1cmVzID0gZ2VuZXMKKQoKIyBQcmludCB0aGUgcGxvdApwcmludChwKQoKZ2dzYXZlKCJUb3A1X0dlbmVzX1Blcl9DbHVzdGVyX0RvdFBsb3QucG5nIiwgcGxvdCA9IHAsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDMwMCkKCgoKCgpgYGAKIyMgdG9wIDUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcgaGVhdG1hcApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCiNhbGxkYXRhIDwtIEFsbF9zYW1wbGVzX01lcmdlZAoKbGlicmFyeShkcGx5cikKCiMgU2VsZWN0IHRoZSB0b3AgNSBnZW5lcyBwZXIgY2x1c3RlciwgZW5zdXJpbmcgdW5pcXVlIGdlbmVzIGFjcm9zcyBjbHVzdGVycwp0b3A1X1UgPC0gbWFya2Vyc19nZW5lcyAlPiUKICAgIGFycmFuZ2UocF92YWxfYWRqLCBkZXNjKGF2Z19sb2cyRkMpKSAlPiUgICMgU29ydCBieSBwX3ZhbF9hZGogKGFzY2VuZGluZykgYW5kIGF2Z19sb2cyRkMgKGRlc2NlbmRpbmcpCiAgICBkaXN0aW5jdChnZW5lLCAua2VlcF9hbGwgPSBUUlVFKSAlPiUgICAgICAjIFJlbW92ZSBkdXBsaWNhdGUgZ2VuZXMgYWNyb3NzIGNsdXN0ZXJzCiAgICBncm91cF9ieShjbHVzdGVyKSAlPiUKICAgIHRvcF9uKC01LCBwX3ZhbF9hZGopICU+JSAgICAgICAgICAgICAgICAgICMgU2VsZWN0IHRoZSB0b3AgNSBnZW5lcyBieSBwX3ZhbF9hZGoKICAgIHRvcF9uKDUsIGF2Z19sb2cyRkMpICU+JSAgICAgICAgICAgICAgICAgICMgRnVydGhlciBzZWxlY3QgdGhlIHRvcCA1IGdlbmVzIGJ5IGF2Z19sb2cyRkMKICAgIHVuZ3JvdXAoKQoKIyBPcmRlciBnZW5lcyBieSBjbHVzdGVyCm9yZGVyZWRfZ2VuZXMgPC0gdG9wNV9VICU+JQogICAgYXJyYW5nZShjbHVzdGVyKSAlPiUgICMgU29ydCBieSBjbHVzdGVyCiAgICBwdWxsKGdlbmUpICAgICAgICAgICAgIyBFeHRyYWN0IHRoZSBvcmRlcmVkIGdlbmUgbmFtZXMgYXMgYSB2ZWN0b3IKCiMgU2NhbGUgZGF0YSBmb3IgdGhlIHNlbGVjdGVkIGdlbmVzCmFsbGRhdGEgPC0gU2NhbGVEYXRhKGFsbGRhdGEsIGZlYXR1cmVzID0gYXMuY2hhcmFjdGVyKG9yZGVyZWRfZ2VuZXMpLCBhc3NheSA9ICJSTkEiKQoKIyBDcmVhdGUgdGhlIGhlYXRtYXAgd2l0aCBvcmRlcmVkIGdlbmVzCmhlYXRtYXBfcGxvdCA8LSBEb0hlYXRtYXAoCiAgICBhbGxkYXRhLAogICAgZmVhdHVyZXMgPSBhcy5jaGFyYWN0ZXIob3JkZXJlZF9nZW5lcyksICAjIFVzZSB0aGUgb3JkZXJlZCBnZW5lcwogICAgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwKICAgIGFzc2F5ID0gIlJOQSIsCiAgICBzaXplID0gMi41CikKCiMgU2F2ZSB0aGUgaGVhdG1hcCBhcyBhIFBORyBpbWFnZSAod2l0aCAzMDAgZHBpIGZvciBoaWdoLXF1YWxpdHkgcHVibGljYXRpb24pCmdnc2F2ZSgidG9wNV9VX21hcmtlcl9nZW5lc19oZWF0bWFwLnBuZyIsIHBsb3QgPSBoZWF0bWFwX3Bsb3QsIHdpZHRoID0gMTIsIGhlaWdodCA9IDgsIGRwaSA9IDMwMCkKCmBgYAoKCiMjIHRvcCA1IG92ZXJleHByZXNzZWQgZ2VuZXMgZm9yIHBsb3R0aW5nIGRvdHBsb3QKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CiMgYWxsZGF0YSA8LSBBbGxfc2FtcGxlc19NZXJnZWQKIyAgIAojIERvdFBsb3QoYWxsZGF0YSwgZmVhdHVyZXMgPSByZXYoYXMuY2hhcmFjdGVyKHVuaXF1ZSh0b3A1X1UkZ2VuZSkpKSwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgYXNzYXkgPSAiUk5BIikgKyBjb29yZF9mbGlwKCkKIyAKIyAjIFNhdmUgbWFya2VyIGdlbmVzIHRvIGEgQ1NWIGZpbGUKIyAjd3JpdGUuY3N2KHRvcDI1LCBmaWxlID0gIlRvcDI1X21hcmtlcnNfZ2VuZXNfUk5BX1dpbGNveC5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQojIAojIAojICMgU2F2ZSBtYXJrZXIgZ2VuZXMgdG8gYSBDU1YgZmlsZQojIHdyaXRlLmNzdih0b3A1X1UsIGZpbGUgPSAidG9wNV9VX21hcmtlcnNfZ2VuZXNfUk5BX1dpbGNveC5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQoKbGlicmFyeShkcGx5cikKCiMgT3JkZXIgZ2VuZXMgYnkgY2x1c3RlcgpvcmRlcmVkX2dlbmVzIDwtIHRvcDVfVSAlPiUKICAgIGFycmFuZ2UoY2x1c3RlcikgJT4lICAjIFNvcnQgYnkgY2x1c3RlcgogICAgcHVsbChnZW5lKSAgICAgICAgICAgICMgRXh0cmFjdCB0aGUgb3JkZXJlZCBnZW5lIG5hbWVzIGFzIGEgdmVjdG9yCgojIENyZWF0ZSB0aGUgRG90UGxvdCB3aXRoIG9yZGVyZWQgZ2VuZXMKZG90cGxvdCA8LSBEb3RQbG90KAogICAgYWxsZGF0YSwKICAgIGZlYXR1cmVzID0gcmV2KGFzLmNoYXJhY3RlcihvcmRlcmVkX2dlbmVzKSksICAjIFJldmVyc2UgdGhlIG9yZGVyIGZvciBjb29yZF9mbGlwKCkKICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICBhc3NheSA9ICJSTkEiCikgKyBjb29yZF9mbGlwKCkKCiMgRGlzcGxheSB0aGUgRG90UGxvdApwcmludChkb3RwbG90KQoKIyBTYXZlIHRoZSBEb3RQbG90IGFzIGEgaGlnaC1yZXNvbHV0aW9uIGltYWdlCmdnc2F2ZSgidG9wNV9VX21hcmtlcl9nZW5lc19kb3RwbG90LnBuZyIsIHBsb3QgPSBkb3RwbG90LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApCgojIFNhdmUgdGhlIG9yZGVyZWQgbWFya2VyIGdlbmVzIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KHRvcDVfVSAlPiUgYXJyYW5nZShjbHVzdGVyKSwgZmlsZSA9ICJ0b3A1X1VfbWFya2Vyc19nZW5lc19STkFfV2lsY294LmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCgoKCmBgYAoKCgoKCgoKIyMgc2NQdWJyIEdyb3VwLVdpc2UgREUgYW5hbHlzaXMgUGxvdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCmxpYnJhcnkoc2NDdXN0b21pemUpCgp0b3A1X1UgPC0gdG9wNV9VWyFkdXBsaWNhdGVkKHRvcDVfVSRnZW5lKSwgXQoKcDQgPC0gRG90UGxvdF9zY0N1c3RvbShzZXVyYXRfb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCBmZWF0dXJlcyA9IG9yZGVyZWRfZ2VuZXMsIHhfbGFiX3JvdGF0ZSA9IFRSVUUpCgpwNAoKcDUgPC0gRG90UGxvdF9zY0N1c3RvbShzZXVyYXRfb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCBmZWF0dXJlcyA9IG9yZGVyZWRfZ2VuZXMsIGZsaXBfYXhlcyA9IFQsCiAgICByZW1vdmVfYXhpc190aXRsZXMgPSBGQUxTRSkKCnA1CgpwNiA8LSBDbHVzdGVyZWRfRG90UGxvdChzZXVyYXRfb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCBmZWF0dXJlcyA9IG9yZGVyZWRfZ2VuZXMsIGsgPSA4KQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAoKcDYKCmBgYAoKCgojIyBzY1B1YnIgR3JvdXAtV2lzZSBERSBhbmFseXNpcyBQbG90CmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQoKbGlicmFyeShTQ3B1YnIpCgojIENyZWF0ZSBhIG5hbWVkIGxpc3Qgb2YgZ2VuZXMgZm9yIGVhY2ggY2x1c3RlcgojZ2VuZXMgPC0gc3BsaXQodG9wNV9VJGdlbmUsIHRvcDVfVSRjbHVzdGVyKQoKIyBHZW5lcmF0ZSB0aGUgZG90IHBsb3QKcCA8LSBTQ3B1YnI6OmRvX0RvdFBsb3QoCiAgICBzYW1wbGUgPSBBbGxfc2FtcGxlc19NZXJnZWQsICAjIFJlcGxhY2Ugd2l0aCB5b3VyIFNldXJhdCBvYmplY3QKICAgIGZlYXR1cmVzID0gb3JkZXJlZF9nZW5lcwopCgojIFByaW50IHRoZSBwbG90CnByaW50KHApCgpnZ3NhdmUoInRvcDVfVV9HZW5lc19QZXJfQ2x1c3Rlcl9Eb3RQbG90LnBuZyIsIHBsb3QgPSBwLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApCgoKCgoKYGBgCgoKCgoKCgoKCgoKCgoK