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


DefaultAssay(All_samples_Merged) <- "RNA"

# Normalize the RNA assay
#All_samples_Merged <- NormalizeData(All_samples_Merged, assay = "RNA", normalization.method = "LogNormalize", scale.factor = 10000)


# Compute differentiall expression
markers_genes <- FindAllMarkers(
    All_samples_Merged,
    test.use = "wilcox",
    logfc.threshold = 0.25,
    min.pct = 0.25,
    only.pos = TRUE,
    assay = "RNA"
)
Calculating cluster 0
Calculating cluster 1
Calculating cluster 2
Calculating cluster 3
Calculating cluster 4
Calculating cluster 5
Calculating cluster 6
Calculating cluster 7
Calculating cluster 8
Calculating cluster 9
Calculating cluster 10
Calculating cluster 11
Calculating cluster 12
Calculating cluster 13
# Save marker genes to a CSV file
write.csv(markers_genes, file = "Top_markers_genes_RNA_Wilcox.csv", row.names = TRUE)

4. top 25 overexpressed genes for plotting.


markers_genes %>%
    group_by(cluster) %>%
    top_n(-25, p_val_adj) %>%
    # In case of tied p-values, further select the top 25 genes by fold-change
    top_n(25, avg_log2FC) -> top25 
  top25
head(top25)

# Save to PDF with high resolution
pdf("Top25_Markers_Barplots.pdf", width = 12, height = 8)

# Set up multi-panel layout and margins
par(mfrow = c(2, 5), mar = c(4, 6, 3, 1))

# Loop over clusters
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))
}
# Close the PDF device
dev.off()
null device 
          1 
# Open a PNG device to save the plot
png("Top25_Markers_Barplots.png", width = 2400, height = 1600, res = 300)

# Create the bar plots
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))
}

# Close the PNG device
dev.off()
null device 
          1 
# 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
  
markers_genes %>%
    group_by(cluster) %>%
    slice_min(p_val_adj, n = 5, with_ties = FALSE) -> top5
# 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%
DoHeatmap(alldata, features = as.character(unique(top5$gene)), group.by = "seurat_clusters", assay = "RNA")

# Save the heatmap as a PNG image (with 300 dpi for high-quality publication)
ggsave("top5_marker_genes_heatmap.png", plot = heatmap_plot, width = 8, height = 6, dpi = 300)
Erreur dans plot_theme(plot) : objet 'heatmap_plot' introuvable

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()

NA
NA

7. scPubr Group-Wise DE analysis Plot

p2 <- SCpubr::do_GroupwiseDEPlot(sample = alldata,
                                de_genes = markers_genes,
                                top_genes = 5)
Avis : aucun argument trouvé pour min ; Inf est renvoyéErreur dans if (dmax - dmin < eps) { : 
  valeur manquante là où TRUE / FALSE est requis

8. scPubr Group-Wise DE analysis Plot


library(scCustomize)

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
)

# Print the plot
print(p)


ggsave("Top5_Genes_Per_Cluster_DotPlot.png", plot = p, width = 12, height = 8, dpi = 300)

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")
Centering and scaling data matrix

  |                                                                                                         
  |                                                                                                   |   0%
  |                                                                                                         
  |===================================================================================================| 100%
# 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
[[1]]

[[2]]

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)
LS0tCnRpdGxlOiAiV2lsY294IEFuYWx5c2lzIFJOQSBUb3AgTWFya2VycyIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIGh0bWxfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogICAgZGZfcHJpbnQ6IHBhZ2VkCiAgcGRmX2RvY3VtZW50OgogICAgdG9jOiB5ZXMKLS0tCgojIDEuIGxvYWQgbGlicmFyaWVzCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQoKc3VwcHJlc3NQYWNrYWdlU3RhcnR1cE1lc3NhZ2VzKHsKICAgIGxpYnJhcnkoU2V1cmF0KQogICAgbGlicmFyeShkcGx5cikKICAgIGxpYnJhcnkocGF0Y2h3b3JrKQogICAgbGlicmFyeShnZ3Bsb3QyKQogICAgbGlicmFyeShwaGVhdG1hcCkKICAgIGxpYnJhcnkoZW5yaWNoUikKICAgIGxpYnJhcnkoTWF0cml4KQogICAgbGlicmFyeShlZGdlUikKICAgIGxpYnJhcnkoTUFTVCkKfSkKCmBgYAoKCiMgMi4gbG9hZCBzZXVyYXQgb2JqZWN0CmBgYHtyIGxvYWRfc2V1cmF0fQojTG9hZCBTZXVyYXQgT2JqZWN0CmxvYWQoIi9ob21lL25hYmJhc2kvaXNpbG9uL1RvX1RyYW5zZmVyX2JldHdlZW5fY29tcHV0ZXJzLzIzLUhhcm1vbnlfSW50ZWdyYXRpb24vMC1yb2JqLzUtSGFybW9ueV9JbnRlZ3JhdGVkX0FsbF9zYW1wbGVzX01lcmdlZF9DRDRUY2VsbHNfZmluYWxfUmVzb2x1dGlvbl9TZWxlY3RlZF8wLjhfQURUX05vcm1hbGl6ZWRfY2xlYW5lZF9tdC5yb2JqIikKCgoKTGF5ZXJzKEFsbF9zYW1wbGVzX01lcmdlZEBhc3NheXMkUk5BKQoKCgoKCmBgYAoKIyAzLiBjbHVzdGVycyB2cyB0aGUgcmVzdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCkRlZmF1bHRBc3NheShBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJSTkEiCgojIE5vcm1hbGl6ZSB0aGUgUk5BIGFzc2F5CiNBbGxfc2FtcGxlc19NZXJnZWQgPC0gTm9ybWFsaXplRGF0YShBbGxfc2FtcGxlc19NZXJnZWQsIGFzc2F5ID0gIlJOQSIsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIkxvZ05vcm1hbGl6ZSIsIHNjYWxlLmZhY3RvciA9IDEwMDAwKQoKCiMgQ29tcHV0ZSBkaWZmZXJlbnRpYWxsIGV4cHJlc3Npb24KbWFya2Vyc19nZW5lcyA8LSBGaW5kQWxsTWFya2VycygKICAgIEFsbF9zYW1wbGVzX01lcmdlZCwKICAgIHRlc3QudXNlID0gIndpbGNveCIsCiAgICBsb2dmYy50aHJlc2hvbGQgPSAwLjI1LAogICAgbWluLnBjdCA9IDAuMjUsCiAgICBvbmx5LnBvcyA9IFRSVUUsCiAgICBhc3NheSA9ICJSTkEiCikKCiMgU2F2ZSBtYXJrZXIgZ2VuZXMgdG8gYSBDU1YgZmlsZQp3cml0ZS5jc3YobWFya2Vyc19nZW5lcywgZmlsZSA9ICJUb3BfbWFya2Vyc19nZW5lc19STkFfV2lsY294LmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCgpgYGAKIyA0LiB0b3AgMjUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcuCmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQoKbWFya2Vyc19nZW5lcyAlPiUKICAgIGdyb3VwX2J5KGNsdXN0ZXIpICU+JQogICAgdG9wX24oLTI1LCBwX3ZhbF9hZGopICU+JQogICAgIyBJbiBjYXNlIG9mIHRpZWQgcC12YWx1ZXMsIGZ1cnRoZXIgc2VsZWN0IHRoZSB0b3AgMjUgZ2VuZXMgYnkgZm9sZC1jaGFuZ2UKICAgIHRvcF9uKDI1LCBhdmdfbG9nMkZDKSAtPiB0b3AyNSAKICB0b3AyNQpoZWFkKHRvcDI1KQoKIyBTYXZlIHRvIFBERiB3aXRoIGhpZ2ggcmVzb2x1dGlvbgpwZGYoIlRvcDI1X01hcmtlcnNfQmFycGxvdHMucGRmIiwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gOCkKCiMgU2V0IHVwIG11bHRpLXBhbmVsIGxheW91dCBhbmQgbWFyZ2lucwpwYXIobWZyb3cgPSBjKDIsIDUpLCBtYXIgPSBjKDQsIDYsIDMsIDEpKQoKIyBMb29wIG92ZXIgY2x1c3RlcnMKZm9yIChpIGluIHVuaXF1ZSh0b3AyNSRjbHVzdGVyKSkgewogICAgYmFycGxvdChzb3J0KHNldE5hbWVzKHRvcDI1JGF2Z19sb2cyRkMsIHRvcDI1JGdlbmUpW3RvcDI1JGNsdXN0ZXIgPT0gaV0sIEYpLAogICAgICAgIGhvcml6ID0gVCwgbGFzID0gMSwgbWFpbiA9IHBhc3RlMChpLCAiIHZzLiByZXN0IiksIGJvcmRlciA9ICJ3aGl0ZSIsIHlheHMgPSAiaSIKICAgICkKICAgIGFibGluZSh2ID0gYygwLCAwLjI1KSwgbHR5ID0gYygxLCAyKSkKfQojIENsb3NlIHRoZSBQREYgZGV2aWNlCmRldi5vZmYoKQoKIyBPcGVuIGEgUE5HIGRldmljZSB0byBzYXZlIHRoZSBwbG90CnBuZygiVG9wMjVfTWFya2Vyc19CYXJwbG90cy5wbmciLCB3aWR0aCA9IDI0MDAsIGhlaWdodCA9IDE2MDAsIHJlcyA9IDMwMCkKCiMgQ3JlYXRlIHRoZSBiYXIgcGxvdHMKcGFyKG1mcm93ID0gYygyLCA1KSwgbWFyID0gYyg0LCA2LCAzLCAxKSkKZm9yIChpIGluIHVuaXF1ZSh0b3AyNSRjbHVzdGVyKSkgewogICAgYmFycGxvdChzb3J0KHNldE5hbWVzKHRvcDI1JGF2Z19sb2cyRkMsIHRvcDI1JGdlbmUpW3RvcDI1JGNsdXN0ZXIgPT0gaV0sIEYpLAogICAgICAgIGhvcml6ID0gVCwgbGFzID0gMSwgbWFpbiA9IHBhc3RlMChpLCAiIHZzLiByZXN0IiksIGJvcmRlciA9ICJ3aGl0ZSIsIHlheHMgPSAiaSIKICAgICkKICAgIGFibGluZSh2ID0gYygwLCAwLjI1KSwgbHR5ID0gYygxLCAyKSkKfQoKIyBDbG9zZSB0aGUgUE5HIGRldmljZQpkZXYub2ZmKCkKCiMgU2FtZSBwbG90dGluZyBjb21tYW5kcwpQMSA8LSBwYXIobWZyb3cgPSBjKDIsIDUpLCBtYXIgPSBjKDQsIDYsIDMsIDEpKQpmb3IgKGkgaW4gdW5pcXVlKHRvcDI1JGNsdXN0ZXIpKSB7CiAgICBiYXJwbG90KHNvcnQoc2V0TmFtZXModG9wMjUkYXZnX2xvZzJGQywgdG9wMjUkZ2VuZSlbdG9wMjUkY2x1c3RlciA9PSBpXSwgRiksCiAgICAgICAgaG9yaXogPSBULCBsYXMgPSAxLCBtYWluID0gcGFzdGUwKGksICIgdnMuIHJlc3QiKSwgYm9yZGVyID0gIndoaXRlIiwgeWF4cyA9ICJpIgogICAgKQogICAgYWJsaW5lKHYgPSBjKDAsIDAuMjUpLCBsdHkgPSBjKDEsIDIpKQp9CgoKUDEKCgoKCgoKYGBgCgoKCiMgNS4gdG9wIDUgb3ZlcmV4cHJlc3NlZCBnZW5lcyBmb3IgcGxvdHRpbmcgaGVhdG1hcApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KYWxsZGF0YSA8LSBBbGxfc2FtcGxlc19NZXJnZWQKICAKbWFya2Vyc19nZW5lcyAlPiUKICAgIGdyb3VwX2J5KGNsdXN0ZXIpICU+JQogICAgc2xpY2VfbWluKHBfdmFsX2FkaiwgbiA9IDUsIHdpdGhfdGllcyA9IEZBTFNFKSAtPiB0b3A1CiMgY3JlYXRlIGEgc2NhbGUuZGF0YSBzbG90IGZvciB0aGUgc2VsZWN0ZWQgZ2VuZXMKYWxsZGF0YSA8LSBTY2FsZURhdGEoYWxsZGF0YSwgZmVhdHVyZXMgPSBhcy5jaGFyYWN0ZXIodW5pcXVlKHRvcDUkZ2VuZSkpLCBhc3NheSA9ICJSTkEiKQpoZWF0bWFwX3Bsb3QgPC0gRG9IZWF0bWFwKGFsbGRhdGEsIGZlYXR1cmVzID0gYXMuY2hhcmFjdGVyKHVuaXF1ZSh0b3A1JGdlbmUpKSwgZ3JvdXAuYnkgPSAic2V1cmF0X2NsdXN0ZXJzIiwgYXNzYXkgPSAiUk5BIiwgc2l6ZSA9IDIuNSkKCiMgU2F2ZSB0aGUgaGVhdG1hcCBhcyBhIFBORyBpbWFnZSAod2l0aCAzMDAgZHBpIGZvciBoaWdoLXF1YWxpdHkgcHVibGljYXRpb24pCmdnc2F2ZSgidG9wNV9tYXJrZXJfZ2VuZXNfaGVhdG1hcC5wbmciLCBwbG90ID0gaGVhdG1hcF9wbG90LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApCgoKYGBgCgoKIyA2LiB0b3AgNSBvdmVyZXhwcmVzc2VkIGdlbmVzIGZvciBwbG90dGluZyBkb3RwbG90CmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQphbGxkYXRhIDwtIEFsbF9zYW1wbGVzX01lcmdlZAogIApEb3RQbG90KGFsbGRhdGEsIGZlYXR1cmVzID0gcmV2KGFzLmNoYXJhY3Rlcih1bmlxdWUodG9wNSRnZW5lKSkpLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBhc3NheSA9ICJSTkEiKSArIGNvb3JkX2ZsaXAoKQoKIyBTYXZlIG1hcmtlciBnZW5lcyB0byBhIENTViBmaWxlCndyaXRlLmNzdih0b3AyNSwgZmlsZSA9ICJUb3AyNV9tYXJrZXJzX2dlbmVzX1JOQV9XaWxjb3guY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkKCgojIFNhdmUgbWFya2VyIGdlbmVzIHRvIGEgQ1NWIGZpbGUKd3JpdGUuY3N2KHRvcDUsIGZpbGUgPSAiVG9wNV9tYXJrZXJzX2dlbmVzX1JOQV9XaWxjb3guY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkKYGBgCgojIDcuIHNjUHViciBHcm91cC1XaXNlIERFIGFuYWx5c2lzIFBsb3QKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CgojIGxpYnJhcnkoU0NwdWJyKQojIAojIHAxIDwtIFNDcHVicjo6ZG9fR3JvdXB3aXNlREVQbG90KHNhbXBsZSA9IGFsbGRhdGEsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV9nZW5lcyA9IG1hcmtlcnNfZ2VuZXMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4uY3V0b2ZmID0gMSkKIyAKIyBwMQojIAojIHAyIDwtIFNDcHVicjo6ZG9fR3JvdXB3aXNlREVQbG90KHNhbXBsZSA9IGFsbGRhdGEsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZV9nZW5lcyA9IG1hcmtlcnNfZ2VuZXMsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfZ2VuZXMgPSA1KQojIAojIHAyCiMgCiMgcDMgPC0gU0NwdWJyOjpkb19Hcm91cHdpc2VERVBsb3Qoc2FtcGxlID0gYWxsZGF0YSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlX2dlbmVzID0gbWFya2Vyc19nZW5lcywKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwLmJ5ID0gYygic2V1cmF0X2NsdXN0ZXJzIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgImNlbGxfbGluZSIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJQYXRpZW50X29yaWdpbiIpLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93X3RpdGxlX2V4cHJlc3Npb24gPSBjKCIiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJjZWxsX2xpbmUiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJEb25vciIpKQojICAgICAgIAojIAojIHAzCgpgYGAKCgojIDguIHNjUHViciBHcm91cC1XaXNlIERFIGFuYWx5c2lzIFBsb3QKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CgpsaWJyYXJ5KHNjQ3VzdG9taXplKQoKdG9wNSA8LSB0b3A1WyFkdXBsaWNhdGVkKHRvcDUkZ2VuZSksIF0KCnA0IDwtIERvdFBsb3Rfc2NDdXN0b20oc2V1cmF0X29iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSB0b3A1JGdlbmUsIHhfbGFiX3JvdGF0ZSA9IFRSVUUpCgpwNAoKcDUgPC0gRG90UGxvdF9zY0N1c3RvbShzZXVyYXRfb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCBmZWF0dXJlcyA9IHRvcDUkZ2VuZSwgZmxpcF9heGVzID0gVCwKICAgIHJlbW92ZV9heGlzX3RpdGxlcyA9IEZBTFNFKQoKcDUKCnA2IDwtIENsdXN0ZXJlZF9Eb3RQbG90KHNldXJhdF9vYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQsIGZlYXR1cmVzID0gdG9wNSRnZW5lLCBrID0gOCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKCnA2CgpgYGAKIyA3LiBzY1B1YnIgR3JvdXAtV2lzZSBERSBhbmFseXNpcyBQbG90CmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQoKbGlicmFyeShTQ3B1YnIpCgojIENyZWF0ZSBhIG5hbWVkIGxpc3Qgb2YgZ2VuZXMgZm9yIGVhY2ggY2x1c3RlcgpnZW5lcyA8LSBzcGxpdCh0b3A1JGdlbmUsIHRvcDUkY2x1c3RlcikKCiMgR2VuZXJhdGUgdGhlIGRvdCBwbG90CnAgPC0gU0NwdWJyOjpkb19Eb3RQbG90KAogICAgc2FtcGxlID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCAgIyBSZXBsYWNlIHdpdGggeW91ciBTZXVyYXQgb2JqZWN0CiAgICBmZWF0dXJlcyA9IGdlbmVzCikKCiMgUHJpbnQgdGhlIHBsb3QKcHJpbnQocCkKCmdnc2F2ZSgiVG9wNV9HZW5lc19QZXJfQ2x1c3Rlcl9Eb3RQbG90LnBuZyIsIHBsb3QgPSBwLCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApCgoKCgoKYGBgCiMjIHRvcCA1IG92ZXJleHByZXNzZWQgZ2VuZXMgZm9yIHBsb3R0aW5nIGhlYXRtYXAKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CgojYWxsZGF0YSA8LSBBbGxfc2FtcGxlc19NZXJnZWQKCmxpYnJhcnkoZHBseXIpCgojIFNlbGVjdCB0aGUgdG9wIDUgZ2VuZXMgcGVyIGNsdXN0ZXIsIGVuc3VyaW5nIHVuaXF1ZSBnZW5lcyBhY3Jvc3MgY2x1c3RlcnMKdG9wNV9VIDwtIG1hcmtlcnNfZ2VuZXMgJT4lCiAgICBhcnJhbmdlKHBfdmFsX2FkaiwgZGVzYyhhdmdfbG9nMkZDKSkgJT4lICAjIFNvcnQgYnkgcF92YWxfYWRqIChhc2NlbmRpbmcpIGFuZCBhdmdfbG9nMkZDIChkZXNjZW5kaW5nKQogICAgZGlzdGluY3QoZ2VuZSwgLmtlZXBfYWxsID0gVFJVRSkgJT4lICAgICAgIyBSZW1vdmUgZHVwbGljYXRlIGdlbmVzIGFjcm9zcyBjbHVzdGVycwogICAgZ3JvdXBfYnkoY2x1c3RlcikgJT4lCiAgICB0b3BfbigtNSwgcF92YWxfYWRqKSAlPiUgICAgICAgICAgICAgICAgICAjIFNlbGVjdCB0aGUgdG9wIDUgZ2VuZXMgYnkgcF92YWxfYWRqCiAgICB0b3Bfbig1LCBhdmdfbG9nMkZDKSAlPiUgICAgICAgICAgICAgICAgICAjIEZ1cnRoZXIgc2VsZWN0IHRoZSB0b3AgNSBnZW5lcyBieSBhdmdfbG9nMkZDCiAgICB1bmdyb3VwKCkKCiMgT3JkZXIgZ2VuZXMgYnkgY2x1c3RlcgpvcmRlcmVkX2dlbmVzIDwtIHRvcDVfVSAlPiUKICAgIGFycmFuZ2UoY2x1c3RlcikgJT4lICAjIFNvcnQgYnkgY2x1c3RlcgogICAgcHVsbChnZW5lKSAgICAgICAgICAgICMgRXh0cmFjdCB0aGUgb3JkZXJlZCBnZW5lIG5hbWVzIGFzIGEgdmVjdG9yCgojIFNjYWxlIGRhdGEgZm9yIHRoZSBzZWxlY3RlZCBnZW5lcwphbGxkYXRhIDwtIFNjYWxlRGF0YShhbGxkYXRhLCBmZWF0dXJlcyA9IGFzLmNoYXJhY3RlcihvcmRlcmVkX2dlbmVzKSwgYXNzYXkgPSAiUk5BIikKCiMgQ3JlYXRlIHRoZSBoZWF0bWFwIHdpdGggb3JkZXJlZCBnZW5lcwpoZWF0bWFwX3Bsb3QgPC0gRG9IZWF0bWFwKAogICAgYWxsZGF0YSwKICAgIGZlYXR1cmVzID0gYXMuY2hhcmFjdGVyKG9yZGVyZWRfZ2VuZXMpLCAgIyBVc2UgdGhlIG9yZGVyZWQgZ2VuZXMKICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsCiAgICBhc3NheSA9ICJSTkEiLAogICAgc2l6ZSA9IDIuNQopCgojIFNhdmUgdGhlIGhlYXRtYXAgYXMgYSBQTkcgaW1hZ2UgKHdpdGggMzAwIGRwaSBmb3IgaGlnaC1xdWFsaXR5IHB1YmxpY2F0aW9uKQpnZ3NhdmUoInRvcDVfVV9tYXJrZXJfZ2VuZXNfaGVhdG1hcC5wbmciLCBwbG90ID0gaGVhdG1hcF9wbG90LCB3aWR0aCA9IDEyLCBoZWlnaHQgPSA4LCBkcGkgPSAzMDApCgpgYGAKCgojIyB0b3AgNSBvdmVyZXhwcmVzc2VkIGdlbmVzIGZvciBwbG90dGluZyBkb3RwbG90CmBgYHtyICwgZmlnLmhlaWdodD0xNCwgZmlnLndpZHRoPTE4fQojIGFsbGRhdGEgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkCiMgICAKIyBEb3RQbG90KGFsbGRhdGEsIGZlYXR1cmVzID0gcmV2KGFzLmNoYXJhY3Rlcih1bmlxdWUodG9wNV9VJGdlbmUpKSksIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIGFzc2F5ID0gIlJOQSIpICsgY29vcmRfZmxpcCgpCiMgCiMgIyBTYXZlIG1hcmtlciBnZW5lcyB0byBhIENTViBmaWxlCiMgI3dyaXRlLmNzdih0b3AyNSwgZmlsZSA9ICJUb3AyNV9tYXJrZXJzX2dlbmVzX1JOQV9XaWxjb3guY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkKIyAKIyAKIyAjIFNhdmUgbWFya2VyIGdlbmVzIHRvIGEgQ1NWIGZpbGUKIyB3cml0ZS5jc3YodG9wNV9VLCBmaWxlID0gInRvcDVfVV9tYXJrZXJzX2dlbmVzX1JOQV9XaWxjb3guY3N2Iiwgcm93Lm5hbWVzID0gVFJVRSkKCmxpYnJhcnkoZHBseXIpCgojIE9yZGVyIGdlbmVzIGJ5IGNsdXN0ZXIKb3JkZXJlZF9nZW5lcyA8LSB0b3A1X1UgJT4lCiAgICBhcnJhbmdlKGNsdXN0ZXIpICU+JSAgIyBTb3J0IGJ5IGNsdXN0ZXIKICAgIHB1bGwoZ2VuZSkgICAgICAgICAgICAjIEV4dHJhY3QgdGhlIG9yZGVyZWQgZ2VuZSBuYW1lcyBhcyBhIHZlY3RvcgoKIyBDcmVhdGUgdGhlIERvdFBsb3Qgd2l0aCBvcmRlcmVkIGdlbmVzCmRvdHBsb3QgPC0gRG90UGxvdCgKICAgIGFsbGRhdGEsCiAgICBmZWF0dXJlcyA9IHJldihhcy5jaGFyYWN0ZXIob3JkZXJlZF9nZW5lcykpLCAgIyBSZXZlcnNlIHRoZSBvcmRlciBmb3IgY29vcmRfZmxpcCgpCiAgICBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLAogICAgYXNzYXkgPSAiUk5BIgopICsgY29vcmRfZmxpcCgpCgojIERpc3BsYXkgdGhlIERvdFBsb3QKcHJpbnQoZG90cGxvdCkKCiMgU2F2ZSB0aGUgRG90UGxvdCBhcyBhIGhpZ2gtcmVzb2x1dGlvbiBpbWFnZQpnZ3NhdmUoInRvcDVfVV9tYXJrZXJfZ2VuZXNfZG90cGxvdC5wbmciLCBwbG90ID0gZG90cGxvdCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gOCwgZHBpID0gMzAwKQoKIyBTYXZlIHRoZSBvcmRlcmVkIG1hcmtlciBnZW5lcyB0byBhIENTViBmaWxlCndyaXRlLmNzdih0b3A1X1UgJT4lIGFycmFuZ2UoY2x1c3RlciksIGZpbGUgPSAidG9wNV9VX21hcmtlcnNfZ2VuZXNfUk5BX1dpbGNveC5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQoKCgpgYGAKCgoKCgoKCiMjIHNjUHViciBHcm91cC1XaXNlIERFIGFuYWx5c2lzIFBsb3QKYGBge3IgLCBmaWcuaGVpZ2h0PTE0LCBmaWcud2lkdGg9MTh9CgpsaWJyYXJ5KHNjQ3VzdG9taXplKQoKdG9wNV9VIDwtIHRvcDVfVVshZHVwbGljYXRlZCh0b3A1X1UkZ2VuZSksIF0KCnA0IDwtIERvdFBsb3Rfc2NDdXN0b20oc2V1cmF0X29iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSBvcmRlcmVkX2dlbmVzLCB4X2xhYl9yb3RhdGUgPSBUUlVFKQoKcDQKCnA1IDwtIERvdFBsb3Rfc2NDdXN0b20oc2V1cmF0X29iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSBvcmRlcmVkX2dlbmVzLCBmbGlwX2F4ZXMgPSBULAogICAgcmVtb3ZlX2F4aXNfdGl0bGVzID0gRkFMU0UpCgpwNQoKcDYgPC0gQ2x1c3RlcmVkX0RvdFBsb3Qoc2V1cmF0X29iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgZmVhdHVyZXMgPSBvcmRlcmVkX2dlbmVzLCBrID0gOCkKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKCnA2CgpgYGAKCgoKIyMgc2NQdWJyIEdyb3VwLVdpc2UgREUgYW5hbHlzaXMgUGxvdApgYGB7ciAsIGZpZy5oZWlnaHQ9MTQsIGZpZy53aWR0aD0xOH0KCmxpYnJhcnkoU0NwdWJyKQoKIyBDcmVhdGUgYSBuYW1lZCBsaXN0IG9mIGdlbmVzIGZvciBlYWNoIGNsdXN0ZXIKI2dlbmVzIDwtIHNwbGl0KHRvcDVfVSRnZW5lLCB0b3A1X1UkY2x1c3RlcikKCiMgR2VuZXJhdGUgdGhlIGRvdCBwbG90CnAgPC0gU0NwdWJyOjpkb19Eb3RQbG90KAogICAgc2FtcGxlID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCAgIyBSZXBsYWNlIHdpdGggeW91ciBTZXVyYXQgb2JqZWN0CiAgICBmZWF0dXJlcyA9IG9yZGVyZWRfZ2VuZXMKKQoKIyBQcmludCB0aGUgcGxvdApwcmludChwKQoKZ2dzYXZlKCJ0b3A1X1VfR2VuZXNfUGVyX0NsdXN0ZXJfRG90UGxvdC5wbmciLCBwbG90ID0gcCwgd2lkdGggPSAxMiwgaGVpZ2h0ID0gOCwgZHBpID0gMzAwKQoKCgoKCmBgYAoKCgoKCgoKCgoKCgoKCg==