1. load libraries
2. Load Seurat Object


All_samples_Merged <- SetIdent(All_samples_Merged, value = "cell_line")
DimPlot(All_samples_Merged,group.by = "cell_line",
reduction = "umap",
label.size = 3,
repel = T,
label = T)
DimPlot(All_samples_Merged,group.by = "cell_line",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)
DimPlot(All_samples_Merged,
group.by = "seurat_clusters",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)

cluster_table <- table(Idents(All_samples_Merged))
DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T)

library(clustree)
clustree(All_samples_Merged, prefix = "SCT_snn_res.")

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l1",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T, label.box = T)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l1",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = F)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T, label.box = T)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = F)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2",
reduction = "umap.harmony",
label.size = 3,
repel = T,
label = T, label.box = T)

table(All_samples_Merged$predicted.celltype.l2, All_samples_Merged$SCT_snn_res.0.5)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
ASDC 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0
B intermediate 0 1 0 0 0 0 3 0 664 1 17 4 0 2 2 2 0 0
B memory 7 3 0 7 14 0 3 205 261 0 2 4 0 13 1 2 1 0
B naive 0 1 0 0 0 0 4 0 1170 1 2 13 0 0 1 0 0 0
CD14 Mono 3 1 8 0 0 20 2595 39 0 0 814 327 6 0 0 7 3 0
CD16 Mono 1 0 0 0 0 0 4 0 0 0 120 1 0 0 0 0 0 0
CD4 CTL 0 0 0 0 0 0 0 0 0 16 0 1 0 0 0 0 0 0
CD4 Naive 0 1989 0 0 0 0 0 0 7 0 0 6 0 0 40 0 0 1
CD4 Proliferating 10573 8 4839 6254 5489 412 1 738 2 1 0 23 48 490 132 1 0 0
CD4 TCM 909 5922 335 115 212 2649 18 1293 65 38 32 398 579 43 256 3 0 11
CD4 TEM 0 80 0 0 0 1 0 0 0 10 0 3 0 0 0 0 0 0
CD8 Naive 0 1330 0 0 0 0 0 0 2 1 1 20 1 0 17 0 1 0
CD8 Proliferating 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0
CD8 TCM 1 370 9 0 0 0 0 0 2 80 0 6 7 0 1 0 0 1
CD8 TEM 0 64 6 0 1 0 1 6 1 305 0 0 0 0 7 0 0 0
cDC1 0 0 0 0 0 0 13 5 0 0 0 0 0 2 1 21 0 0
cDC2 0 0 1 1 2 0 123 45 0 0 1 0 0 3 0 53 0 0
dnT 0 31 0 0 0 1 0 7 2 0 3 17 0 0 20 0 0 1
gdT 0 15 0 0 0 0 0 0 0 78 0 0 0 0 0 0 0 0
HSPC 55 0 0 1429 258 3 6 11 1 1 0 3 6 38 7 4 7 5
ILC 0 0 0 0 0 0 0 0 1 4 0 1 0 0 1 0 0 0
MAIT 0 9 0 0 0 0 0 0 0 227 0 3 0 0 3 0 0 0
NK 0 0 0 0 0 0 0 0 1 523 1 7 0 0 2 0 0 0
NK Proliferating 24 0 2818 15 254 0 0 6 0 2 0 4 0 11 32 0 1 0
NK_CD56bright 0 0 0 0 0 0 0 0 0 14 0 0 0 0 2 0 0 0
pDC 0 0 0 0 0 0 56 0 0 0 0 0 0 0 0 0 0 0
Plasmablast 0 0 0 0 0 0 5 0 13 0 0 0 0 0 1 0 0 0
Platelet 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 0 30 0
Treg 0 258 1 0 0 0 0 9 5 0 0 40 0 0 39 1 0 0
3. Perform DE analysis using the FindMarkers or FindAllMarkers
function
# Find markers for all clusters
All_markers_default <- FindAllMarkers(All_samples_Merged)
Calculating cluster L1
Calculating cluster L2
Calculating cluster L3
Calculating cluster L4
Calculating cluster L5
Calculating cluster L6
Calculating cluster L7
Calculating cluster PBMC
Calculating cluster PBMC_10x
All_markers_Default_min_diff <- FindAllMarkers(All_samples_Merged,
min.pct = 0.25,
logfc.threshold = 0.25)
Calculating cluster L1
Calculating cluster L2
Calculating cluster L3
Calculating cluster L4
Calculating cluster L5
Calculating cluster L6
Calculating cluster L7
Calculating cluster PBMC
Calculating cluster PBMC_10x
All_markers_0.5_min_diff <- FindAllMarkers(All_samples_Merged,
min.pct = 0.25,
logfc.threshold = 0.25,
min.pct.diff= 0.5)
Calculating cluster L1
Calculating cluster L2
Calculating cluster L3
Calculating cluster L4
Calculating cluster L5
Calculating cluster L6
Calculating cluster L7
Calculating cluster PBMC
Calculating cluster PBMC_10x
Patient_cell_lines_vs_PBMC_Tcells <- FindMarkers(All_samples_Merged,
ident.1 = c("2", "5", "12", "0", "3", "4", "7", "13"),
ident.2 = c("1", "9", "11", "14", "17")
)
Error in WhichCells.Seurat(object = object, idents = ident.1) :
Cannot find the following identities in the object: 2512034713
EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells ,
lab=rownames(Patient_cell_lines_vs_PBMC_Tcells),
x ="avg_log2FC",
y ="p_val_adj",
title = "Sézary Cell Lines vs PBMC T cells",
pCutoff = 0.05,
FCcutoff = 1,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells ,
lab=rownames(Patient_cell_lines_vs_PBMC_Tcells),
x ="avg_log2FC",
y ="p_val_adj",
selectLab = c('EPCAM','BCAT1','KIR3DL2',
'FOXM1','TWIST1','TNFSF9','CD80','CD7','IL1B', 'TRBV7.6','TRBV5.4','TRBV12.4'),
title = "Sézary Cell Lines vs PBMC T cells",
xlab = bquote(~Log[2]~ 'fold change'),
pCutoff = 0.05,
FCcutoff = 1,
legendPosition = 'right',
legendLabSize = 14,
legendIconSize = 4.0,
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.75,
colConnectors = 'black')
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells,
lab = ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05,
rownames(Patient_cell_lines_vs_PBMC_Tcells),
""), # Label only significant genes
x = "avg_log2FC",
y = "p_val_adj",
title = "Sézary Cell Lines vs PBMC T cells",
pCutoff = 0.05,
FCcutoff = 1,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

EnhancedVolcano(Patient_cell_lines_vs_PBMC_Tcells,
lab = ifelse((Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 | Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5) &
Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05,
rownames(Patient_cell_lines_vs_PBMC_Tcells),
""), # Label only significant genes
x = "avg_log2FC",
y = "p_val_adj",
title = "Sézary Cell Lines vs PBMC T cells",
pCutoff = 0.05,
FCcutoff = 1,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 5.0,
drawConnectors = TRUE,
widthConnectors = 0.25)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

All_samples_Merged <- SetIdent(All_samples_Merged, value = "SCT_snn_res.0.9")
L2_Thesholds <- FindMarkers(All_samples_Merged, ident.1 = "4", ident.2 = "9", min.pct = 0.10, thresh.use = 0.25)
EnhancedVolcano(L2_Thesholds ,
lab=rownames(L2_Thesholds),
x ="avg_log2FC",
y ="p_val_adj",
title = "4_vs_9",
pCutoff = 0.05,
FCcutoff = 1,
legendPosition = 'right',
labCol = 'black',
labFace = 'bold',
boxedLabels = TRUE,
pointSize = 3.0,
labSize = 3.0,
drawConnectors = FALSE,
widthConnectors = 0.75)
Warning: One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

4. Enrichment Analysis
#Step-by-Step Guide for Gene Set Enrichment Analysis (GSEA) or Over-Representation Analysis (ORA)
# Load the packages
library(clusterProfiler)
clusterProfiler v4.13.4 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
S Xu, E Hu, Y Cai, Z Xie, X Luo, L Zhan, W Tang, Q Wang, B Liu, R Wang, W Xie, T Wu, L Xie, G Yu. Using
clusterProfiler to characterize multiomics data. Nature Protocols. 2024, doi:10.1038/s41596-024-01020-z
Attaching package: 'clusterProfiler'
The following object is masked from 'package:stats':
filter
library(org.Hs.eg.db)
Loading required package: AnnotationDbi
Loading required package: stats4
Loading required package: BiocGenerics
Attaching package: 'BiocGenerics'
The following object is masked from 'package:gridExtra':
combine
The following objects are masked from 'package:dplyr':
combine, intersect, setdiff, union
The following object is masked from 'package:SeuratObject':
intersect
The following objects are masked from 'package:stats':
IQR, mad, sd, var, xtabs
The following objects are masked from 'package:base':
anyDuplicated, aperm, append, as.data.frame, basename, cbind, colnames, dirname, do.call, duplicated, eval,
evalq, Filter, Find, get, grep, grepl, intersect, is.unsorted, lapply, Map, mapply, match, mget, order, paste,
pmax, pmax.int, pmin, pmin.int, Position, rank, rbind, Reduce, rownames, sapply, saveRDS, setdiff, table,
tapply, union, unique, unsplit, which.max, which.min
Loading required package: Biobase
Welcome to Bioconductor
Vignettes contain introductory material; view with 'browseVignettes()'. To cite Bioconductor, see
'citation("Biobase")', and for packages 'citation("pkgname")'.
Loading required package: IRanges
Loading required package: S4Vectors
Attaching package: 'S4Vectors'
The following object is masked from 'package:clusterProfiler':
rename
The following objects are masked from 'package:dplyr':
first, rename
The following object is masked from 'package:utils':
findMatches
The following objects are masked from 'package:base':
expand.grid, I, unname
Attaching package: 'IRanges'
The following object is masked from 'package:clusterProfiler':
slice
The following objects are masked from 'package:dplyr':
collapse, desc, slice
The following object is masked from 'package:sp':
%over%
Attaching package: 'AnnotationDbi'
The following object is masked from 'package:clusterProfiler':
select
The following object is masked from 'package:dplyr':
select
library(enrichplot)
enrichplot v1.25.3 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
Guangchuang Yu, Fei Li, Yide Qin, Xiaochen Bo, Yibo Wu and Shengqi Wang. GOSemSim: an R package for measuring
semantic similarity among GO terms and gene products. Bioinformatics. 2010, 26(7):976-978
library(ReactomePA)
ReactomePA v1.49.1 Learn more at https://yulab-smu.top/contribution-knowledge-mining/
Please cite:
Guangchuang Yu, Qing-Yu He. ReactomePA: an R/Bioconductor package for reactome pathway analysis and visualization.
Molecular BioSystems. 2016, 12(2):477-479
# Get upregulated genes
upregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])
# Get downregulated genes
downregulated_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5 & Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05, ])
#Gene Ontology (GO) Enrichment Analysis
# GO enrichment for upregulated genes
go_up <- enrichGO(gene = upregulated_genes,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP", # "BP" for Biological Processes, "MF" for Molecular Function, "CC" for Cellular Component
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# GO enrichment for downregulated genes
go_down <- enrichGO(gene = downregulated_genes,
OrgDb = org.Hs.eg.db,
keyType = "SYMBOL",
ont = "BP",
pAdjustMethod = "BH",
pvalueCutoff = 0.05)
# Visualize the top enriched GO terms
dotplot(go_up, showCategory = 20, title = "GO Enrichment for Upregulated Genes")

dotplot(go_down, showCategory = 20, title = "GO Enrichment for Downregulated Genes")

#KEGG Pathway Enrichment
# Convert gene symbols to Entrez IDs for KEGG analysis
upregulated_entrez <- bitr(upregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:many mapping between keys and columns
Warning: 10.64% of input gene IDs are fail to map...
downregulated_entrez <- bitr(downregulated_genes, fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)$ENTREZID
'select()' returned 1:1 mapping between keys and columns
Warning: 14.88% of input gene IDs are fail to map...
# KEGG pathway enrichment for upregulated genes
kegg_up <- enrichKEGG(gene = upregulated_entrez,
organism = "hsa",
pvalueCutoff = 0.05)
Reading KEGG annotation online: "https://rest.kegg.jp/link/hsa/pathway"...
Reading KEGG annotation online: "https://rest.kegg.jp/list/pathway/hsa"...
# KEGG pathway enrichment for downregulated genes
kegg_down <- enrichKEGG(gene = downregulated_entrez,
organism = "hsa",
pvalueCutoff = 0.05)
# Visualize KEGG pathway results
dotplot(kegg_up, showCategory = 20, title = "KEGG Pathway Enrichment for Upregulated Genes")

dotplot(kegg_down, showCategory = 20, title = "KEGG Pathway Enrichment for Downregulated Genes")

#Reactome Pathway Enrichment
# Reactome pathway enrichment for upregulated genes
reactome_up <- enrichPathway(gene = upregulated_entrez,
organism = "human",
pvalueCutoff = 0.05)
# Reactome pathway enrichment for downregulated genes
reactome_down <- enrichPathway(gene = downregulated_entrez,
organism = "human",
pvalueCutoff = 0.05)
# Visualize Reactome pathways
dotplot(reactome_up, showCategory = 20, title = "Reactome Pathway Enrichment for Upregulated Genes")

dotplot(reactome_down, showCategory = 20, title = "Reactome Pathway Enrichment for Downregulated Genes")

# Gene Set Enrichment Analysis (GSEA) (Optional)
# Create a ranked list of genes
gene_list <- Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC
names(gene_list) <- rownames(Patient_cell_lines_vs_PBMC_Tcells)
gene_list <- sort(gene_list, decreasing = TRUE)
# Convert gene symbols to Entrez IDs
gene_df <- bitr(names(gene_list), fromType = "SYMBOL", toType = "ENTREZID", OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Warning: 11.13% of input gene IDs are fail to map...
# Ensure the gene list matches the Entrez IDs
gene_list <- gene_list[names(gene_list) %in% gene_df$SYMBOL]
# Replace gene symbols with Entrez IDs
names(gene_list) <- gene_df$ENTREZID[match(names(gene_list), gene_df$SYMBOL)]
# Run GSEA using KEGG
gsea_kegg <- gseKEGG(geneList = gene_list,
organism = "hsa",
pvalueCutoff = 0.05)
using 'fgsea' for GSEA analysis, please cite Korotkevich et al (2019).
preparing geneSet collections...
GSEA analysis...
Warning: There are ties in the preranked stats (0.2% of the list).
The order of those tied genes will be arbitrary, which may produce unexpected results.Warning: There were 2 pathways for which P-values were not calculated properly due to unbalanced (positive and negative) gene-level statistic values. For such pathways pval, padj, NES, log2err are set to NA. You can try to increase the value of the argument nPermSimple (for example set it nPermSimple = 10000)Warning: For some of the pathways the P-values were likely overestimated. For such pathways log2err is set to NA.Warning: For some pathways, in reality P-values are less than 1e-10. You can set the `eps` argument to zero for better estimation.leading edge analysis...
done...
# Plot the GSEA results
gseaplot(gsea_kegg, geneSetID = 1, title = "Top KEGG Pathway")

# Extract the name of the top KEGG pathway
top_pathway <- gsea_kegg@result[1, "Description"]
# Plot GSEA with the top pathway's name as the title
gseaplot(gsea_kegg, geneSetID = 1, title = top_pathway)

NA
NA
5. Bar PLOT
# Filter for significant pathways
top_kegg_up <- kegg_up@result[kegg_up@result$p.adjust < 0.05, ]
top_kegg_down <- kegg_down@result[kegg_down@result$p.adjust < 0.05, ]
# If there are not enough pathways, consider relaxing the threshold or checking the output
top_kegg_up <- top_kegg_up[order(-top_kegg_up$p.adjust), ][1:10, ]
top_kegg_down <- top_kegg_down[order(top_kegg_down$p.adjust), ][1:10, ]
# Combine into one data frame
top_pathways <- rbind(
data.frame(Pathway = top_kegg_up$Description, p.adjust = top_kegg_up$p.adjust, Direction = "Upregulated"),
data.frame(Pathway = top_kegg_down$Description, p.adjust = top_kegg_down$p.adjust, Direction = "Downregulated")
)
# Convert p.adjust to -log10(p.adjust) for visualization
top_pathways$neg_log10_p <- -log10(top_pathways$p.adjust)
# Create the barplot
ggplot(top_pathways, aes(x = reorder(Pathway, neg_log10_p), y = neg_log10_p, fill = Direction)) +
geom_bar(stat = "identity", position = position_dodge()) +
scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
coord_flip() + # Flip the coordinates for better readability
labs(title = "Top Significant Pathways",
x = "Pathways",
y = "-Log10 Adjusted P-Value") +
theme_minimal() +
theme(legend.title = element_blank())

# Load necessary library
library(ggplot2)
# Create the barplot
ggplot(top_pathways, aes(x = Pathway, y = neg_log10_p, fill = Direction)) +
geom_bar(stat = "identity", position = "identity") + # Use position = "identity"
scale_fill_manual(values = c("Upregulated" = "red", "Downregulated" = "blue")) +
coord_flip() + # Flip the coordinates for better readability
labs(title = "Top Significant Pathways",
x = "Pathways",
y = "-Log10 Adjusted P-Value") +
theme_minimal() +
theme(legend.title = element_blank())

NA
NA
NA
5. ggplot2 for Volcano
library(ggplot2)
library(ggrepel)
# Identify top and bottom genes
top_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 2, ]
bottom_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, ]
# Create a new column for color based on significance
Patient_cell_lines_vs_PBMC_Tcells$color <- ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 2, "Top Gene",
ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, "Bottom Gene", "Neutral"))
# Create a volcano plot
ggplot(Patient_cell_lines_vs_PBMC_Tcells, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
geom_point(aes(color = color), alpha = 0.7, size = 2) +
# Add labels for top and bottom genes
geom_text_repel(data = top_genes, aes(label = gene), color = "black", vjust = 1, fontface = "bold") +
geom_text_repel(data = bottom_genes, aes(label = gene), color = "black", vjust = -1, fontface = "bold") +
# Customize labels and title
labs(title = "Volcano Plot",
x = "log2 Fold Change",
y = "-log10(p-value)") +
# Add significance threshold lines
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
geom_vline(xintercept = c(-1.5, 2), linetype = "dashed", color = "black") +
# Set colors for top and bottom genes
scale_color_manual(values = c("Top Gene" = "red", "Bottom Gene" = "blue", "Neutral" = "darkgrey")) +
# Customize theme if needed
theme_minimal()

NA
NA
NA
NA
NA
library(ggplot2)
library(ggrepel)
# Identify top and bottom genes based on criteria
top_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 2, ]
bottom_genes <- Patient_cell_lines_vs_PBMC_Tcells[Patient_cell_lines_vs_PBMC_Tcells$p_val_adj < 0.05 & Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, ]
# Sort and select the most significant top and bottom genes
top_genes <- top_genes[order(top_genes$p_val_adj), ][1:100, ] # Top 100 significant upregulated genes
bottom_genes <- bottom_genes[order(bottom_genes$p_val_adj), ][1:100, ] # Top 100 significant downregulated genes
# Create a new column for color based on significance
Patient_cell_lines_vs_PBMC_Tcells$color <- ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC > 2, "Top Gene",
ifelse(Patient_cell_lines_vs_PBMC_Tcells$avg_log2FC < -1.5, "Bottom Gene", "Neutral"))
# Create a volcano plot
ggplot(Patient_cell_lines_vs_PBMC_Tcells, aes(x = avg_log2FC, y = -log10(p_val_adj))) +
geom_point(aes(color = color), alpha = 0.7, size = 2) +
# Add labels only for top 100 and bottom 100 genes
geom_text_repel(data = top_genes, aes(label = gene), color = "black", vjust = 1, fontface = "bold") +
geom_text_repel(data = bottom_genes, aes(label = gene), color = "black", vjust = -1, fontface = "bold") +
# Customize labels and title
labs(title = "Volcano Plot",
x = "log2 Fold Change",
y = "-log10(p-value)") +
# Add significance threshold lines
geom_hline(yintercept = -log10(0.05), linetype = "dashed", color = "black") +
geom_vline(xintercept = c(-1.5, 2), linetype = "dashed", color = "black") +
# Set colors for top and bottom genes
scale_color_manual(values = c("Top Gene" = "red", "Bottom Gene" = "blue", "Neutral" = "darkgrey")) +
# Customize theme if needed
theme_minimal()

NA
NA
NA
NA
NA
LS0tCnRpdGxlOiAiRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQW5hbHlzaXMgb2YgU1MgdnMgUEJNQzEwWCtQQk1DIgphdXRob3I6IE5hc2lyIE1haG1vb2QgQWJiYXNpCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogICNybWRmb3JtYXRzOjpyZWFkdGhlZG93bgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHRydWUKICAgIHRvY19mbG9hdDogdHJ1ZQogICAgdG9jX2NvbGxhcHNlZDogdHJ1ZQotLS0KCiMgMS4gbG9hZCBsaWJyYXJpZXMKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KFNldXJhdE9iamVjdCkKbGlicmFyeShTZXVyYXREYXRhKQpsaWJyYXJ5KHBhdGNod29yaykKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoY293cGxvdCkKbGlicmFyeShyZXRpY3VsYXRlKQpsaWJyYXJ5KEF6aW11dGgpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoUnRzbmUpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShncmlkRXh0cmEpCmxpYnJhcnkoRW5oYW5jZWRWb2xjYW5vKQpgYGAKCiMgMi4gTG9hZCBTZXVyYXQgT2JqZWN0IApgYGB7ciBsb2FkX3NldXJhdCwgZmlnLmhlaWdodD02LCBmaWcud2lkdGg9MTB9CgogbG9hZCgiL2hvbWUvYmlvaW5mby8xMS1ERS9ERS1QQk1DMTB4X2luY2x1ZGVkL0hhcm1vbnlfaW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfd2l0aF9QQk1DMTB4LlJvYmoiKQogCkFsbF9zYW1wbGVzX01lcmdlZCA8LSBTZXRJZGVudChBbGxfc2FtcGxlc19NZXJnZWQsIHZhbHVlID0gImNlbGxfbGluZSIpCiAgCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLGdyb3VwLmJ5ID0gImNlbGxfbGluZSIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwIiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBUKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsZ3JvdXAuYnkgPSAiY2VsbF9saW5lIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLAogICAgICAgIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IFQpCgpjbHVzdGVyX3RhYmxlIDwtIHRhYmxlKElkZW50cyhBbGxfc2FtcGxlc19NZXJnZWQpKQoKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBUKQoKIGxpYnJhcnkoY2x1c3RyZWUpCiBjbHVzdHJlZShBbGxfc2FtcGxlc19NZXJnZWQsIHByZWZpeCA9ICJTQ1Rfc25uX3Jlcy4iKQoKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDEiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIGdyb3VwLmJ5ID0gInByZWRpY3RlZC5jZWxsdHlwZS5sMSIsIAogICAgICAgIHJlZHVjdGlvbiA9ICJ1bWFwLmhhcm1vbnkiLAogICAgICAgIGxhYmVsLnNpemUgPSAzLAogICAgICAgIHJlcGVsID0gVCwKICAgICAgICBsYWJlbCA9IEYpCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgZ3JvdXAuYnkgPSAicHJlZGljdGVkLmNlbGx0eXBlLmwyIiwgCiAgICAgICAgcmVkdWN0aW9uID0gInVtYXAuaGFybW9ueSIsCiAgICAgICAgbGFiZWwuc2l6ZSA9IDMsCiAgICAgICAgcmVwZWwgPSBULAogICAgICAgIGxhYmVsID0gVCwgbGFiZWwuYm94ID0gVCkKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBGKQoKCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCAKICAgICAgICByZWR1Y3Rpb24gPSAidW1hcC5oYXJtb255IiwKICAgICAgICBsYWJlbC5zaXplID0gMywKICAgICAgICByZXBlbCA9IFQsCiAgICAgICAgbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKdGFibGUoQWxsX3NhbXBsZXNfTWVyZ2VkJHByZWRpY3RlZC5jZWxsdHlwZS5sMiwgQWxsX3NhbXBsZXNfTWVyZ2VkJFNDVF9zbm5fcmVzLjAuNSkKYGBgCgoKIyAzLiBQZXJmb3JtIERFIGFuYWx5c2lzIHVzaW5nIHRoZSBGaW5kTWFya2VycyBvciBGaW5kQWxsTWFya2VycyBmdW5jdGlvbgpgYGB7ciBkYXRhMSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CiMgRmluZCBtYXJrZXJzIGZvciBhbGwgY2x1c3RlcnMKQWxsX21hcmtlcnNfZGVmYXVsdCA8LSBGaW5kQWxsTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQpCgpBbGxfbWFya2Vyc19EZWZhdWx0X21pbl9kaWZmICA8LSBGaW5kQWxsTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4ucGN0ID0gMC4yNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZmMudGhyZXNob2xkID0gMC4yNSkKCkFsbF9tYXJrZXJzXzAuNV9taW5fZGlmZiA8LSBGaW5kQWxsTWFya2VycyhBbGxfc2FtcGxlc19NZXJnZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW4ucGN0ID0gMC4yNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbG9nZmMudGhyZXNob2xkID0gMC4yNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluLnBjdC5kaWZmPSAwLjUpCgpBbGxfc2FtcGxlc19NZXJnZWQgPC0gU2V0SWRlbnQoQWxsX3NhbXBsZXNfTWVyZ2VkLCB2YWx1ZSA9ICJTQ1Rfc25uX3Jlcy4wLjUiKQoKUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzIDwtIEZpbmRNYXJrZXJzKEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkZW50LjEgPSBjKCIyIiwgIjUiLCAiMTIiLCAiMCIsICIzIiwgIjQiLCAiNyIsICIxMyIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICBpZGVudC4yID0gYygiMSIsICI5IiwgIjExIiwgIjE0IiwgIjE3IikKICAgICAgICAgICAgICAgICAgICAgICAgICAgKQoKIyBFbnN1cmUgQWxsX21hcmtlcnNfZGVmYXVsdCBpcyBhIGRhdGEgZnJhbWUKQWxsX21hcmtlcnNfZGVmYXVsdCA8LSBhcy5kYXRhLmZyYW1lKEFsbF9tYXJrZXJzX2RlZmF1bHQpCgojIFJlcGVhdCBmb3IgdGhlIG90aGVyIGRhdGEgZnJhbWVzCkFsbF9tYXJrZXJzX0RlZmF1bHRfbWluX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShBbGxfbWFya2Vyc19EZWZhdWx0X21pbl9kaWZmKQpBbGxfbWFya2Vyc18wLjVfbWluX2RpZmYgPC0gYXMuZGF0YS5mcmFtZShBbGxfbWFya2Vyc18wLjVfbWluX2RpZmYpCgoKIyBTYXZlIEFsbF9tYXJrZXJzX2RlZmF1bHQgdG8gQ1NWCndyaXRlLmNzdihBbGxfbWFya2Vyc19kZWZhdWx0LCAiQWxsX21hcmtlcnNfZGVmYXVsdC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCiMgU2F2ZSBBbGxfbWFya2Vyc19EZWZhdWx0X21pbl9kaWZmIHRvIENTVgp3cml0ZS5jc3YoQWxsX21hcmtlcnNfRGVmYXVsdF9taW5fZGlmZiwgIkFsbF9tYXJrZXJzX0RlZmF1bHRfbWluX2RpZmYuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgojIFNhdmUgQWxsX21hcmtlcnNfMC41X21pbl9kaWZmIHRvIENTVgp3cml0ZS5jc3YoQWxsX21hcmtlcnNfMC41X21pbl9kaWZmLCAiQWxsX21hcmtlcnNfMC41X21pbl9kaWZmLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKIyBDb252ZXJ0IHRvIGRhdGEgZnJhbWUgYW5kIGFkZCBnZW5lIG5hbWVzIGFzIGEgbmV3IGNvbHVtbgpQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgPC0gYXMuZGF0YS5mcmFtZShQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRnZW5lIDwtIHJvd25hbWVzKFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscykKCiMgUmVhcnJhbmdpbmcgdGhlIGNvbHVtbnMgZm9yIGJldHRlciByZWFkYWJpbGl0eSAob3B0aW9uYWwpClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyA8LSBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbLCBjKCJnZW5lIiwgInBfdmFsIiwgImF2Z19sb2cyRkMiLCAicGN0LjEiLCAicGN0LjIiLCAicF92YWxfYWRqIildCgp3cml0ZS5jc3YoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzLCAiUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKCmBgYAoKYGBge3IgZW5oYW5jZWRWLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMgLCAKICAgICAgICAgICAgICAgIGxhYj1yb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMpLAogICAgICAgICAgICAgICAgeCA9ImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSJwX3ZhbF9hZGoiLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiU8OpemFyeSBDZWxsIExpbmVzIHZzIFBCTUMgVCBjZWxscyIsCiAgICAgICAgICAgICAgICBwQ3V0b2ZmID0gMC4wNSwKICAgICAgICAgICAgICAgIEZDY3V0b2ZmID0gMSwgCiAgICAgICAgICAgICAgICBsZWdlbmRQb3NpdGlvbiA9ICdyaWdodCcsIAogICAgICAgICAgICAgICAgbGFiQ29sID0gJ2JsYWNrJywKICAgICAgICAgICAgICAgIGxhYkZhY2UgPSAnYm9sZCcsCiAgICAgICAgICAgICAgICBib3hlZExhYmVscyA9IFRSVUUsCiAgICAgICAgICAgICAgICBwb2ludFNpemUgPSAzLjAsCiAgICAgICAgICAgICAgICBsYWJTaXplID0gNS4wLCAKICAgICAgICAgICAgICAgIGRyYXdDb25uZWN0b3JzID0gVFJVRSwKICAgICAgICAgICAgICAgIHdpZHRoQ29ubmVjdG9ycyA9IDAuMjUpCgpFbmhhbmNlZFZvbGNhbm8oUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzICwgCiAgICAgICAgICAgICAgICBsYWI9cm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKSwKICAgICAgICAgICAgICAgIHggPSJhdmdfbG9nMkZDIiwgCiAgICAgICAgICAgICAgICB5ID0icF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHNlbGVjdExhYiA9IGMoJ0VQQ0FNJywnQkNBVDEnLCdLSVIzREwyJywKICAgICAgJ0ZPWE0xJywnVFdJU1QxJywnVE5GU0Y5JywnQ0Q4MCcsJ0NENycsJ0lMMUInLCAnVFJCVjcuNicsJ1RSQlY1LjQnLCdUUkJWMTIuNCcpLAogICAgICAgICAgICAgICAgdGl0bGUgPSAiU8OpemFyeSBDZWxsIExpbmVzIHZzIFBCTUMgVCBjZWxscyIsCiAgICAgICAgICAgICAgICAgeGxhYiA9IGJxdW90ZSh+TG9nWzJdfiAnZm9sZCBjaGFuZ2UnKSwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLCAKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywgCiAgICAgICAgICAgICAgICBsZWdlbmRMYWJTaXplID0gMTQsCiAgICAgICAgICAgICAgICBsZWdlbmRJY29uU2l6ZSA9IDQuMCwKICAgICAgICAgICAgICAgIGxhYkNvbCA9ICdibGFjaycsCiAgICAgICAgICAgICAgICBsYWJGYWNlID0gJ2JvbGQnLAogICAgICAgICAgICAgICAgYm94ZWRMYWJlbHMgPSBUUlVFLAogICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMy4wLAogICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDUuMCwgCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjc1LAogICAgICAgICAgICAgICAgY29sQ29ubmVjdG9ycyA9ICdibGFjaycpCgoKRW5oYW5jZWRWb2xjYW5vKFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscywgCiAgICAgICAgICAgICAgICBsYWIgPSBpZmVsc2UoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAxICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiKSwgICMgTGFiZWwgb25seSBzaWduaWZpY2FudCBnZW5lcwogICAgICAgICAgICAgICAgeCA9ICJhdmdfbG9nMkZDIiwgCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJTw6l6YXJ5IENlbGwgTGluZXMgdnMgUEJNQyBUIGNlbGxzIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLCAKICAgICAgICAgICAgICAgIGxlZ2VuZFBvc2l0aW9uID0gJ3JpZ2h0JywgCiAgICAgICAgICAgICAgICBsYWJDb2wgPSAnYmxhY2snLAogICAgICAgICAgICAgICAgbGFiRmFjZSA9ICdib2xkJywKICAgICAgICAgICAgICAgIGJveGVkTGFiZWxzID0gVFJVRSwKICAgICAgICAgICAgICAgIHBvaW50U2l6ZSA9IDMuMCwKICAgICAgICAgICAgICAgIGxhYlNpemUgPSA1LjAsIAogICAgICAgICAgICAgICAgZHJhd0Nvbm5lY3RvcnMgPSBUUlVFLAogICAgICAgICAgICAgICAgd2lkdGhDb25uZWN0b3JzID0gMC4yNSkKCkVuaGFuY2VkVm9sY2FubyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMsIAogICAgICAgICAgICAgICAgbGFiID0gaWZlbHNlKChQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA+IDEuNSB8IFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSkgJiAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIiIpLCAgIyBMYWJlbCBvbmx5IHNpZ25pZmljYW50IGdlbmVzCiAgICAgICAgICAgICAgICB4ID0gImF2Z19sb2cyRkMiLCAKICAgICAgICAgICAgICAgIHkgPSAicF92YWxfYWRqIiwKICAgICAgICAgICAgICAgIHRpdGxlID0gIlPDqXphcnkgQ2VsbCBMaW5lcyB2cyBQQk1DIFQgY2VsbHMiLAogICAgICAgICAgICAgICAgcEN1dG9mZiA9IDAuMDUsCiAgICAgICAgICAgICAgICBGQ2N1dG9mZiA9IDEsIAogICAgICAgICAgICAgICAgbGVnZW5kUG9zaXRpb24gPSAncmlnaHQnLCAKICAgICAgICAgICAgICAgIGxhYkNvbCA9ICdibGFjaycsCiAgICAgICAgICAgICAgICBsYWJGYWNlID0gJ2JvbGQnLAogICAgICAgICAgICAgICAgYm94ZWRMYWJlbHMgPSBUUlVFLAogICAgICAgICAgICAgICAgcG9pbnRTaXplID0gMy4wLAogICAgICAgICAgICAgICAgbGFiU2l6ZSA9IDUuMCwgCiAgICAgICAgICAgICAgICBkcmF3Q29ubmVjdG9ycyA9IFRSVUUsCiAgICAgICAgICAgICAgICB3aWR0aENvbm5lY3RvcnMgPSAwLjI1KQoKCgoKCgpgYGAKCiMgNC4gRW5yaWNobWVudCBBbmFseXNpcwpgYGB7ciBkYXRhMiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojU3RlcC1ieS1TdGVwIEd1aWRlIGZvciBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSBvciBPdmVyLVJlcHJlc2VudGF0aW9uIEFuYWx5c2lzIChPUkEpCgojIExvYWQgdGhlIHBhY2thZ2VzCmxpYnJhcnkoY2x1c3RlclByb2ZpbGVyKQpsaWJyYXJ5KG9yZy5Icy5lZy5kYikKbGlicmFyeShlbnJpY2hwbG90KQpsaWJyYXJ5KFJlYWN0b21lUEEpCgoKIyBHZXQgdXByZWd1bGF0ZWQgZ2VuZXMKdXByZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDID4gMS41ICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUsIF0pCgojIEdldCBkb3ducmVndWxhdGVkIGdlbmVzCmRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDIDwgLTEuNSAmIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRwX3ZhbF9hZGogPCAwLjA1LCBdKQoKI0dlbmUgT250b2xvZ3kgKEdPKSBFbnJpY2htZW50IEFuYWx5c2lzCiMgR08gZW5yaWNobWVudCBmb3IgdXByZWd1bGF0ZWQgZ2VuZXMKZ29fdXAgPC0gZW5yaWNoR08oZ2VuZSA9IHVwcmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgT3JnRGIgPSBvcmcuSHMuZWcuZGIsIAogICAgICAgICAgICAgICAgICBrZXlUeXBlID0gIlNZTUJPTCIsIAogICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAgICMgIkJQIiBmb3IgQmlvbG9naWNhbCBQcm9jZXNzZXMsICJNRiIgZm9yIE1vbGVjdWxhciBGdW5jdGlvbiwgIkNDIiBmb3IgQ2VsbHVsYXIgQ29tcG9uZW50CiAgICAgICAgICAgICAgICAgIHBBZGp1c3RNZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgR08gZW5yaWNobWVudCBmb3IgZG93bnJlZ3VsYXRlZCBnZW5lcwpnb19kb3duIDwtIGVucmljaEdPKGdlbmUgPSBkb3ducmVndWxhdGVkX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgICBPcmdEYiA9IG9yZy5Icy5lZy5kYiwgCiAgICAgICAgICAgICAgICAgICAga2V5VHlwZSA9ICJTWU1CT0wiLCAKICAgICAgICAgICAgICAgICAgICBvbnQgPSAiQlAiLCAKICAgICAgICAgICAgICAgICAgICBwQWRqdXN0TWV0aG9kID0gIkJIIiwgCiAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlzdWFsaXplIHRoZSB0b3AgZW5yaWNoZWQgR08gdGVybXMKZG90cGxvdChnb191cCwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIkdPIEVucmljaG1lbnQgZm9yIFVwcmVndWxhdGVkIEdlbmVzIikKZG90cGxvdChnb19kb3duLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiR08gRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgojS0VHRyBQYXRod2F5IEVucmljaG1lbnQKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzIGZvciBLRUdHIGFuYWx5c2lzCnVwcmVndWxhdGVkX2VudHJleiA8LSBiaXRyKHVwcmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKZG93bnJlZ3VsYXRlZF9lbnRyZXogPC0gYml0cihkb3ducmVndWxhdGVkX2dlbmVzLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikkRU5UUkVaSUQKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIHVwcmVndWxhdGVkIGdlbmVzCmtlZ2dfdXAgPC0gZW5yaWNoS0VHRyhnZW5lID0gdXByZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImhzYSIsIAogICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgS0VHRyBwYXRod2F5IGVucmljaG1lbnQgZm9yIGRvd25yZWd1bGF0ZWQgZ2VuZXMKa2VnZ19kb3duIDwtIGVucmljaEtFR0coZ2VuZSA9IGRvd25yZWd1bGF0ZWRfZW50cmV6LCAKICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBLRUdHIHBhdGh3YXkgcmVzdWx0cwpkb3RwbG90KGtlZ2dfdXAsIHNob3dDYXRlZ29yeSA9IDIwLCB0aXRsZSA9ICJLRUdHIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgVXByZWd1bGF0ZWQgR2VuZXMiKQpkb3RwbG90KGtlZ2dfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIktFR0cgUGF0aHdheSBFbnJpY2htZW50IGZvciBEb3ducmVndWxhdGVkIEdlbmVzIikKCiNSZWFjdG9tZSBQYXRod2F5IEVucmljaG1lbnQKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciB1cHJlZ3VsYXRlZCBnZW5lcwpyZWFjdG9tZV91cCA8LSBlbnJpY2hQYXRod2F5KGdlbmUgPSB1cHJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gImh1bWFuIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgUmVhY3RvbWUgcGF0aHdheSBlbnJpY2htZW50IGZvciBkb3ducmVndWxhdGVkIGdlbmVzCnJlYWN0b21lX2Rvd24gPC0gZW5yaWNoUGF0aHdheShnZW5lID0gZG93bnJlZ3VsYXRlZF9lbnRyZXosIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHVtYW4iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpc3VhbGl6ZSBSZWFjdG9tZSBwYXRod2F5cwpkb3RwbG90KHJlYWN0b21lX3VwLCBzaG93Q2F0ZWdvcnkgPSAyMCwgdGl0bGUgPSAiUmVhY3RvbWUgUGF0aHdheSBFbnJpY2htZW50IGZvciBVcHJlZ3VsYXRlZCBHZW5lcyIpCmRvdHBsb3QocmVhY3RvbWVfZG93biwgc2hvd0NhdGVnb3J5ID0gMjAsIHRpdGxlID0gIlJlYWN0b21lIFBhdGh3YXkgRW5yaWNobWVudCBmb3IgRG93bnJlZ3VsYXRlZCBHZW5lcyIpCgoKIyBHZW5lIFNldCBFbnJpY2htZW50IEFuYWx5c2lzIChHU0VBKSAoT3B0aW9uYWwpCiMgQ3JlYXRlIGEgcmFua2VkIGxpc3Qgb2YgZ2VuZXMKZ2VuZV9saXN0IDwtIFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRhdmdfbG9nMkZDCm5hbWVzKGdlbmVfbGlzdCkgPC0gcm93bmFtZXMoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzKQpnZW5lX2xpc3QgPC0gc29ydChnZW5lX2xpc3QsIGRlY3JlYXNpbmcgPSBUUlVFKQoKIyBDb252ZXJ0IGdlbmUgc3ltYm9scyB0byBFbnRyZXogSURzCmdlbmVfZGYgPC0gYml0cihuYW1lcyhnZW5lX2xpc3QpLCBmcm9tVHlwZSA9ICJTWU1CT0wiLCB0b1R5cGUgPSAiRU5UUkVaSUQiLCBPcmdEYiA9IG9yZy5Icy5lZy5kYikKCiMgRW5zdXJlIHRoZSBnZW5lIGxpc3QgbWF0Y2hlcyB0aGUgRW50cmV6IElEcwpnZW5lX2xpc3QgPC0gZ2VuZV9saXN0W25hbWVzKGdlbmVfbGlzdCkgJWluJSBnZW5lX2RmJFNZTUJPTF0KCiMgUmVwbGFjZSBnZW5lIHN5bWJvbHMgd2l0aCBFbnRyZXogSURzCm5hbWVzKGdlbmVfbGlzdCkgPC0gZ2VuZV9kZiRFTlRSRVpJRFttYXRjaChuYW1lcyhnZW5lX2xpc3QpLCBnZW5lX2RmJFNZTUJPTCldCgoKIyBSdW4gR1NFQSB1c2luZyBLRUdHCmdzZWFfa2VnZyA8LSBnc2VLRUdHKGdlbmVMaXN0ID0gZ2VuZV9saXN0LCAKICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhIiwgCiAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFBsb3QgdGhlIEdTRUEgcmVzdWx0cwpnc2VhcGxvdChnc2VhX2tlZ2csIGdlbmVTZXRJRCA9IDEsIHRpdGxlID0gIlRvcCBLRUdHIFBhdGh3YXkiKQoKIyBFeHRyYWN0IHRoZSBuYW1lIG9mIHRoZSB0b3AgS0VHRyBwYXRod2F5CnRvcF9wYXRod2F5IDwtIGdzZWFfa2VnZ0ByZXN1bHRbMSwgIkRlc2NyaXB0aW9uIl0KCiMgUGxvdCBHU0VBIHdpdGggdGhlIHRvcCBwYXRod2F5J3MgbmFtZSBhcyB0aGUgdGl0bGUKZ3NlYXBsb3QoZ3NlYV9rZWdnLCBnZW5lU2V0SUQgPSAxLCB0aXRsZSA9IHRvcF9wYXRod2F5KQoKCmBgYAojIDUuIEJhciBQTE9UCmBgYHtyIGRhdGEzLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBGaWx0ZXIgZm9yIHNpZ25pZmljYW50IHBhdGh3YXlzCnRvcF9rZWdnX3VwIDwtIGtlZ2dfdXBAcmVzdWx0W2tlZ2dfdXBAcmVzdWx0JHAuYWRqdXN0IDwgMC4wNSwgXQp0b3Bfa2VnZ19kb3duIDwtIGtlZ2dfZG93bkByZXN1bHRba2VnZ19kb3duQHJlc3VsdCRwLmFkanVzdCA8IDAuMDUsIF0KCiMgSWYgdGhlcmUgYXJlIG5vdCBlbm91Z2ggcGF0aHdheXMsIGNvbnNpZGVyIHJlbGF4aW5nIHRoZSB0aHJlc2hvbGQgb3IgY2hlY2tpbmcgdGhlIG91dHB1dAp0b3Bfa2VnZ191cCA8LSB0b3Bfa2VnZ191cFtvcmRlcigtdG9wX2tlZ2dfdXAkcC5hZGp1c3QpLCBdWzE6MTAsIF0KdG9wX2tlZ2dfZG93biA8LSB0b3Bfa2VnZ19kb3duW29yZGVyKHRvcF9rZWdnX2Rvd24kcC5hZGp1c3QpLCBdWzE6MTAsIF0KCiMgQ29tYmluZSBpbnRvIG9uZSBkYXRhIGZyYW1lCnRvcF9wYXRod2F5cyA8LSByYmluZCgKICBkYXRhLmZyYW1lKFBhdGh3YXkgPSB0b3Bfa2VnZ191cCREZXNjcmlwdGlvbiwgcC5hZGp1c3QgPSB0b3Bfa2VnZ191cCRwLmFkanVzdCwgRGlyZWN0aW9uID0gIlVwcmVndWxhdGVkIiksCiAgZGF0YS5mcmFtZShQYXRod2F5ID0gdG9wX2tlZ2dfZG93biREZXNjcmlwdGlvbiwgcC5hZGp1c3QgPSB0b3Bfa2VnZ19kb3duJHAuYWRqdXN0LCBEaXJlY3Rpb24gPSAiRG93bnJlZ3VsYXRlZCIpCikKCiMgQ29udmVydCBwLmFkanVzdCB0byAtbG9nMTAocC5hZGp1c3QpIGZvciB2aXN1YWxpemF0aW9uCnRvcF9wYXRod2F5cyRuZWdfbG9nMTBfcCA8LSAtbG9nMTAodG9wX3BhdGh3YXlzJHAuYWRqdXN0KQoKIyBDcmVhdGUgdGhlIGJhcnBsb3QKZ2dwbG90KHRvcF9wYXRod2F5cywgYWVzKHggPSByZW9yZGVyKFBhdGh3YXksIG5lZ19sb2cxMF9wKSwgeSA9IG5lZ19sb2cxMF9wLCBmaWxsID0gRGlyZWN0aW9uKSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKCkpICsKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCJVcHJlZ3VsYXRlZCIgPSAicmVkIiwgIkRvd25yZWd1bGF0ZWQiID0gImJsdWUiKSkgKwogIGNvb3JkX2ZsaXAoKSArICAjIEZsaXAgdGhlIGNvb3JkaW5hdGVzIGZvciBiZXR0ZXIgcmVhZGFiaWxpdHkKICBsYWJzKHRpdGxlID0gIlRvcCBTaWduaWZpY2FudCBQYXRod2F5cyIsCiAgICAgICB4ID0gIlBhdGh3YXlzIiwKICAgICAgIHkgPSAiLUxvZzEwIEFkanVzdGVkIFAtVmFsdWUiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgojIExvYWQgbmVjZXNzYXJ5IGxpYnJhcnkKbGlicmFyeShnZ3Bsb3QyKQoKIyBDcmVhdGUgdGhlIGJhcnBsb3QKZ2dwbG90KHRvcF9wYXRod2F5cywgYWVzKHggPSBQYXRod2F5LCB5ID0gbmVnX2xvZzEwX3AsIGZpbGwgPSBEaXJlY3Rpb24pKSArCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHBvc2l0aW9uID0gImlkZW50aXR5IikgKyAgIyBVc2UgcG9zaXRpb24gPSAiaWRlbnRpdHkiCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiVXByZWd1bGF0ZWQiID0gInJlZCIsICJEb3ducmVndWxhdGVkIiA9ICJibHVlIikpICsKICBjb29yZF9mbGlwKCkgKyAgIyBGbGlwIHRoZSBjb29yZGluYXRlcyBmb3IgYmV0dGVyIHJlYWRhYmlsaXR5CiAgbGFicyh0aXRsZSA9ICJUb3AgU2lnbmlmaWNhbnQgUGF0aHdheXMiLAogICAgICAgeCA9ICJQYXRod2F5cyIsCiAgICAgICB5ID0gIi1Mb2cxMCBBZGp1c3RlZCBQLVZhbHVlIikgKwogIHRoZW1lX21pbmltYWwoKSArCiAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKCgpgYGAKCiMgNS4gcGVyZm9ybSBnZW5lIGVucmljaG1lbnQgYW5hbHlzaXMgYW5kIGlkZW50aWZ5IHBhdGh3YXlzCmBgYHtyIGRhdGE0LCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KIyBMb2FkIHRoZSBwYWNrYWdlcwpsaWJyYXJ5KGNsdXN0ZXJQcm9maWxlcikKbGlicmFyeShvcmcuSHMuZWcuZGIpCgojIEFzc3VtaW5nIGBzaWduaWZpY2FudF9nZW5lc2AgaXMgeW91ciBsaXN0IG9mIHNpZ25pZmljYW50IGdlbmUgc3ltYm9scwpzaWduaWZpY2FudF9nZW5lcyA8LSByb3duYW1lcyhQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbCiAgICAoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAxLjUgfCAKICAgICBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUpICYgCiAgICBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkcF92YWxfYWRqIDwgMC4wNSwgXSkKCmVudHJlel9pZHMgPC0gYml0cihzaWduaWZpY2FudF9nZW5lcywgZnJvbVR5cGUgPSAiU1lNQk9MIiwgCiAgICAgICAgICAgICAgICAgICB0b1R5cGUgPSAiRU5UUkVaSUQiLCAKICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiKQoKa2VnZ19yZXN1bHRzIDwtIGVucmljaEtFR0coZ2VuZSA9IGVudHJlel9pZHMkRU5UUkVaSUQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZ2FuaXNtID0gJ2hzYScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgIHB2YWx1ZUN1dG9mZiA9IDAuMDUpCgojIFZpZXcgcmVzdWx0cwpoZWFkKGtlZ2dfcmVzdWx0cykKCgpnb19yZXN1bHRzIDwtIGVucmljaEdPKGdlbmUgPSBlbnRyZXpfaWRzJEVOVFJFWklELAogICAgICAgICAgICAgICAgICAgICAgIE9yZ0RiID0gb3JnLkhzLmVnLmRiLAogICAgICAgICAgICAgICAgICAgICAgIG9udCA9ICJCUCIsICMgQmlvbG9naWNhbCBQcm9jZXNzCiAgICAgICAgICAgICAgICAgICAgICAgcHZhbHVlQ3V0b2ZmID0gMC4wNSkKCiMgVmlldyByZXN1bHRzCmhlYWQoZ29fcmVzdWx0cykKCiMgRG90IHBsb3QgZm9yIEtFR0cgcmVzdWx0cwpkb3RwbG90KGtlZ2dfcmVzdWx0cywgc2hvd0NhdGVnb3J5PTEwKSArIGdndGl0bGUoIktFR0cgUGF0aHdheSBFbnJpY2htZW50IikKCiMgRG90IHBsb3QgZm9yIEdPIHJlc3VsdHMKZG90cGxvdChnb19yZXN1bHRzLCBzaG93Q2F0ZWdvcnk9MTApICsgZ2d0aXRsZSgiR08gQmlvbG9naWNhbCBQcm9jZXNzIEVucmljaG1lbnQiKQoKCmBgYAoKCiMgNS4gZ2dwbG90MiBmb3IgVm9sY2FubwpgYGB7ciBkYXRhNSwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQoKIyBJZGVudGlmeSB0b3AgYW5kIGJvdHRvbSBnZW5lcwp0b3BfZ2VuZXMgPC0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRwX3ZhbF9hZGogPCAwLjA1ICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAyLCBdCmJvdHRvbV9nZW5lcyA8LSBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUgJiBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsIF0KCiMgQ3JlYXRlIGEgbmV3IGNvbHVtbiBmb3IgY29sb3IgYmFzZWQgb24gc2lnbmlmaWNhbmNlClBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRjb2xvciA8LSBpZmVsc2UoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAyLCAiVG9wIEdlbmUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPCAtMS41LCAiQm90dG9tIEdlbmUiLCAiTmV1dHJhbCIpKQoKIyBDcmVhdGUgYSB2b2xjYW5vIHBsb3QKZ2dwbG90KFBhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscywgYWVzKHggPSBhdmdfbG9nMkZDLCB5ID0gLWxvZzEwKHBfdmFsX2FkaikpKSArCiAgZ2VvbV9wb2ludChhZXMoY29sb3IgPSBjb2xvciksIGFscGhhID0gMC43LCBzaXplID0gMikgKwogIAogICMgQWRkIGxhYmVscyBmb3IgdG9wIGFuZCBib3R0b20gZ2VuZXMKICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IHRvcF9nZW5lcywgYWVzKGxhYmVsID0gZ2VuZSksIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAxLCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gYm90dG9tX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IC0xLCBmb250ZmFjZSA9ICJib2xkIikgKwogIAogICMgQ3VzdG9taXplIGxhYmVscyBhbmQgdGl0bGUKICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdCIsCiAgICAgICB4ID0gImxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgeSA9ICItbG9nMTAocC12YWx1ZSkiKSArCiAgCiAgIyBBZGQgc2lnbmlmaWNhbmNlIHRocmVzaG9sZCBsaW5lcwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IC1sb2cxMCgwLjA1KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMS41LCAyKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgCiAgIyBTZXQgY29sb3JzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3AgR2VuZSIgPSAicmVkIiwgIkJvdHRvbSBHZW5lIiA9ICJibHVlIiwgIk5ldXRyYWwiID0gImRhcmtncmV5IikpICsKICAKICAjIEN1c3RvbWl6ZSB0aGVtZSBpZiBuZWVkZWQKICB0aGVtZV9taW5pbWFsKCkKCgoKCgpgYGAKCgpgYGB7ciBkYXRhNiwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShnZ3JlcGVsKQoKIyBJZGVudGlmeSB0b3AgYW5kIGJvdHRvbSBnZW5lcyBiYXNlZCBvbiBjcml0ZXJpYQp0b3BfZ2VuZXMgPC0gUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzW1BhdGllbnRfY2VsbF9saW5lc192c19QQk1DX1RjZWxscyRwX3ZhbF9hZGogPCAwLjA1ICYgUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGF2Z19sb2cyRkMgPiAyLCBdCmJvdHRvbV9nZW5lcyA8LSBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHNbUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJHBfdmFsX2FkaiA8IDAuMDUgJiBQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsIF0KCiMgU29ydCBhbmQgc2VsZWN0IHRoZSBtb3N0IHNpZ25pZmljYW50IHRvcCBhbmQgYm90dG9tIGdlbmVzCnRvcF9nZW5lcyA8LSB0b3BfZ2VuZXNbb3JkZXIodG9wX2dlbmVzJHBfdmFsX2FkaiksIF1bMToxMDAsIF0gICMgVG9wIDEwMCBzaWduaWZpY2FudCB1cHJlZ3VsYXRlZCBnZW5lcwpib3R0b21fZ2VuZXMgPC0gYm90dG9tX2dlbmVzW29yZGVyKGJvdHRvbV9nZW5lcyRwX3ZhbF9hZGopLCBdWzE6MTAwLCBdICAjIFRvcCAxMDAgc2lnbmlmaWNhbnQgZG93bnJlZ3VsYXRlZCBnZW5lcwoKIyBDcmVhdGUgYSBuZXcgY29sdW1uIGZvciBjb2xvciBiYXNlZCBvbiBzaWduaWZpY2FuY2UKUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzJGNvbG9yIDwtIGlmZWxzZShQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA+IDIsICJUb3AgR2VuZSIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShQYXRpZW50X2NlbGxfbGluZXNfdnNfUEJNQ19UY2VsbHMkYXZnX2xvZzJGQyA8IC0xLjUsICJCb3R0b20gR2VuZSIsICJOZXV0cmFsIikpCgojIENyZWF0ZSBhIHZvbGNhbm8gcGxvdApnZ3Bsb3QoUGF0aWVudF9jZWxsX2xpbmVzX3ZzX1BCTUNfVGNlbGxzLCBhZXMoeCA9IGF2Z19sb2cyRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSkpICsKICBnZW9tX3BvaW50KGFlcyhjb2xvciA9IGNvbG9yKSwgYWxwaGEgPSAwLjcsIHNpemUgPSAyKSArCiAgCiAgIyBBZGQgbGFiZWxzIG9ubHkgZm9yIHRvcCAxMDAgYW5kIGJvdHRvbSAxMDAgZ2VuZXMKICBnZW9tX3RleHRfcmVwZWwoZGF0YSA9IHRvcF9nZW5lcywgYWVzKGxhYmVsID0gZ2VuZSksIGNvbG9yID0gImJsYWNrIiwgdmp1c3QgPSAxLCBmb250ZmFjZSA9ICJib2xkIikgKwogIGdlb21fdGV4dF9yZXBlbChkYXRhID0gYm90dG9tX2dlbmVzLCBhZXMobGFiZWwgPSBnZW5lKSwgY29sb3IgPSAiYmxhY2siLCB2anVzdCA9IC0xLCBmb250ZmFjZSA9ICJib2xkIikgKwogIAogICMgQ3VzdG9taXplIGxhYmVscyBhbmQgdGl0bGUKICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdCIsCiAgICAgICB4ID0gImxvZzIgRm9sZCBDaGFuZ2UiLAogICAgICAgeSA9ICItbG9nMTAocC12YWx1ZSkiKSArCiAgCiAgIyBBZGQgc2lnbmlmaWNhbmNlIHRocmVzaG9sZCBsaW5lcwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IC1sb2cxMCgwLjA1KSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0ID0gYygtMS41LCAyKSwgbGluZXR5cGUgPSAiZGFzaGVkIiwgY29sb3IgPSAiYmxhY2siKSArCiAgCiAgIyBTZXQgY29sb3JzIGZvciB0b3AgYW5kIGJvdHRvbSBnZW5lcwogIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXMgPSBjKCJUb3AgR2VuZSIgPSAicmVkIiwgIkJvdHRvbSBHZW5lIiA9ICJibHVlIiwgIk5ldXRyYWwiID0gImRhcmtncmV5IikpICsKICAKICAjIEN1c3RvbWl6ZSB0aGVtZSBpZiBuZWVkZWQKICB0aGVtZV9taW5pbWFsKCkKCgoKCgpgYGAKCg==