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