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. perform gene enrichment analysis and identify pathways

# Load the packages
library(clusterProfiler)
library(org.Hs.eg.db)

# Assuming `significant_genes` is your list of significant gene symbols
significant_genes <- rownames(Patient_cell_lines_vs_PBMC_Tcells[
    (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, ])

entrez_ids <- bitr(significant_genes, fromType = "SYMBOL", 
                   toType = "ENTREZID", 
                   OrgDb = org.Hs.eg.db)
'select()' returned 1:many mapping between keys and columns
Warning: 11.08% of input gene IDs are fail to map...
kegg_results <- enrichKEGG(gene = entrez_ids$ENTREZID,
                           organism = 'hsa',
                           pvalueCutoff = 0.05)

# View results
head(kegg_results)


go_results <- enrichGO(gene = entrez_ids$ENTREZID,
                       OrgDb = org.Hs.eg.db,
                       ont = "BP", # Biological Process
                       pvalueCutoff = 0.05)

# View results
head(go_results)

# Dot plot for KEGG results
dotplot(kegg_results, showCategory=10) + ggtitle("KEGG Pathway Enrichment")


# Dot plot for GO results
dotplot(go_results, showCategory=10) + ggtitle("GO Biological Process Enrichment")

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==