1. load libraries
2. Load Seurat Object
#Load Seurat Object merged from cell lines and a control after filtration
load("../0-robj/5-Harmony_Integrated_All_samples_Merged_CD4Tcells_final_Resolution_Selected_0.8_ADT_Normalized_cleaned_mt.robj")
3. Visulization of Harmony integrated Object
DefaultAssay(All_samples_Merged) <- "SCT"
DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters", label = TRUE, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap", group.by = "orig.ident", label = TRUE, label.box = T)

DimPlot(All_samples_Merged, group.by = "predicted.celltype.l2", label = F)

3. DE Analysis Using RNA Assay (Log-Normalized Counts)
# Set the default assay to RNA
DefaultAssay(All_samples_Merged) <- "RNA"
# Perform LogNormalization on the RNA assay
All_samples_Merged <- NormalizeData(All_samples_Merged, normalization.method = "LogNormalize", scale.factor = 10000)
Normalizing layer: counts
Performing log-normalization
0% 10 20 30 40 50 60 70 80 90 100%
[----|----|----|----|----|----|----|----|----|----|
**************************************************|
# Set identity class to cell line
Idents(All_samples_Merged) <- "cell_line"
# Define malignant and normal cell lines
malignant_cell_line <- c("L1", "L2", "L3", "L4", "L5", "L6", "L7")
normal_cell_line <- c("PBMC", "PBMC_10x")
# Perform DE analysis using RNA assay
DE_RNA <- FindMarkers(
object = All_samples_Merged,
ident.1 = malignant_cell_line,
ident.2 = normal_cell_line,
assay = "RNA", # Use RNA-normalized counts
min.pct = 0,
logfc.threshold = 0
)
# Convert to data frame and add gene names
DE_RNA <- as.data.frame(DE_RNA)
DE_RNA$gene <- rownames(DE_RNA)
# Reorder columns
DE_RNA <- DE_RNA[, c("gene", "p_val", "avg_log2FC", "pct.1", "pct.2", "p_val_adj")]
# Save results
write.csv(DE_RNA, "Malignant_CD4Tcells_vs_Normal_CD4Tcells_RNA_Assay.csv", row.names = FALSE)
5. DE Analysis Visualize Results of RNA vs SCT
comparison_avg_log2FC_RNA
library(ggplot2)
common_genes <- intersect(DE_RNA$gene, DE_SCT$gene)
RNA_values <- DE_RNA[DE_RNA$gene %in% common_genes, ]
SCT_values <- DE_SCT[DE_SCT$gene %in% common_genes, ]
comparison_df <- merge(RNA_values, SCT_values, by = "gene", suffixes = c("_RNA", "_SCT"))
ggplot(comparison_df, aes(x = avg_log2FC_RNA, y = avg_log2FC_SCT)) +
geom_point() +
geom_abline(slope = 1, intercept = 0, color = "red") +
theme_minimal() +
labs(title = "Comparison of DE Results: RNA vs SCT", x = "Log2FC (RNA)", y = "Log2FC (SCT)")

6. DE Analysis Visualize Results of RNA vs SCT
comparison_p_val_adj
library(ggplot2)
# Find common genes present in both DE results
common_genes <- intersect(DE_RNA$gene, DE_SCT$gene)
# Extract the values for the common genes
RNA_values <- DE_RNA[DE_RNA$gene %in% common_genes, ]
SCT_values <- DE_SCT[DE_SCT$gene %in% common_genes, ]
# Merge both datasets on "gene" column
comparison_df <- merge(RNA_values, SCT_values, by = "gene", suffixes = c("_RNA", "_SCT"))
# Plot adjusted p-values (log-transformed for better visualization)
ggplot(comparison_df, aes(x = -log10(p_val_adj_RNA), y = -log10(p_val_adj_SCT))) +
geom_point(alpha = 0.5) + # Transparency for better visibility
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") + # Diagonal reference line
theme_minimal() +
labs(
title = "Comparison of Adjusted p-values: RNA vs SCT",
x = "-log10 Adjusted p-value (RNA)",
y = "-log10 Adjusted p-value (SCT)"
) +
theme(
plot.title = element_text(hjust = 0.5), # Center the title
axis.text = element_text(size = 12),
axis.title = element_text(size = 14)
)

NA
NA
Why Use MAST? Handles zero inflation (dropouts) in
single-cell RNA-seq data. Accounts for technical and biological
variation. Works well when adjusting for covariates (Patient_origin
& cell_line).
7. DE Analysis Using RNA Assay (Log-Normalized Counts) + MAST
# # Load required package for MAST
# library(MAST)
#
# # Set the default assay to RNA
# DefaultAssay(All_samples_Merged) <- "RNA"
#
# # Perform LogNormalization on the RNA assay
# All_samples_Merged <- NormalizeData(All_samples_Merged, normalization.method = "LogNormalize", scale.factor = 10000)
DefaultAssay(All_samples_Merged) <- "RNA"
# Set identity class to cell line
Idents(All_samples_Merged) <- "cell_line"
# Define malignant and normal cell lines
malignant_cell_line_L1 <- c("L1")
normal_CD4Tcells <- c("PBMC", "PBMC_10x")
# Perform DE analysis using RNA assay with MAST and covariates
DE_RNA_MAST <- FindMarkers(
object = All_samples_Merged,
ident.1 = malignant_cell_line_L1,
ident.2 = normal_CD4Tcells,
assay = "RNA", # Use RNA-normalized counts
test.use = "MAST", # Use MAST test
min.pct = 0,
logfc.threshold = 0,
latent.vars = c("Patient_origin", "cell_line") # Adjust for patient and cell line
)
# Convert to data frame and add gene names
DE_RNA_MAST <- as.data.frame(DE_RNA_MAST)
DE_RNA_MAST$gene <- rownames(DE_RNA_MAST)
# Reorder columns
DE_RNA_MAST <- DE_RNA_MAST[, c("gene", "p_val", "avg_log2FC", "pct.1", "pct.2", "p_val_adj")]
# Save results
write.csv(DE_RNA_MAST, "Malignant_CD4Tcells_L1_vs_Normal_CD4Tcells_RNA_MAST.csv", row.names = FALSE)
9. DE Analysis Visualize Results of RNA vs SCT
comparison_avg_log2FC_RNA
# Load required libraries
library(ggplot2)
library(ggrepel) # For better labeling of outlier genes
# Load DE results
DE_RNA_MAST <- read.csv("Malignant_CD4Tcells_L1_vs_Normal_CD4Tcells_RNA_MAST.csv")
DE_SCT_MAST <- read.csv("Malignant_CD4Tcells_L1_vs_Normal_CD4Tcells_SCT_MAST.csv")
# Find common genes in both datasets
common_genes <- intersect(DE_RNA_MAST$gene, DE_SCT_MAST$gene)
# Filter for common genes
RNA_values <- DE_RNA_MAST[DE_RNA_MAST$gene %in% common_genes, ]
SCT_values <- DE_SCT_MAST[DE_SCT_MAST$gene %in% common_genes, ]
# Merge datasets
comparison_df <- merge(RNA_values, SCT_values, by = "gene", suffixes = c("_RNA", "_SCT"))
# ---- PLOT 1: Log2 Fold Change (Log2FC) Comparison ----
p1 <- ggplot(comparison_df, aes(x = avg_log2FC_RNA, y = avg_log2FC_SCT)) +
geom_point(alpha = 0.5) +
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") + # Diagonal reference line
theme_minimal() +
labs(title = "Log2 Fold Change (Log2FC) Comparison: RNA vs SCT (MAST)",
x = "Log2 Fold Change (RNA)",
y = "Log2 Fold Change (SCT)") +
theme(plot.title = element_text(hjust = 0.5))
# ---- PLOT 2: Adjusted p-value (p_val_adj) Comparison ----
p2 <- ggplot(comparison_df, aes(x = -log10(p_val_adj_RNA), y = -log10(p_val_adj_SCT))) +
geom_point(alpha = 0.5) +
geom_abline(slope = 1, intercept = 0, color = "red", linetype = "dashed") + # Reference line
theme_minimal() +
labs(title = "Adjusted p-value (-log10) Comparison: RNA vs SCT (MAST)",
x = "-log10 Adjusted p-value (RNA)",
y = "-log10 Adjusted p-value (SCT)") +
theme(plot.title = element_text(hjust = 0.5))
# ---- PLOT BOTH ----
library(gridExtra)
grid.arrange(p1, p2, ncol = 2)
LS0tCnRpdGxlOiAiREUoTWFsaWduYXRfdnNfTm9ybWFsX0NENFRjZWxscykgb2YgSGFybW9ueSBJbnRlZ3JhdGlvbiIKYXV0aG9yOiBOYXNpciBNYWhtb29kIEFiYmFzaQpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICAjcm1kZm9ybWF0czo6cmVhZHRoZWRvd24KICBodG1sX25vdGVib29rOgogICAgdG9jOiB0cnVlCiAgICB0b2NfZmxvYXQ6IHRydWUKICAgIHRvY19jb2xsYXBzZWQ6IHRydWUKLS0tCgoKIyAxLiBsb2FkIGxpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoU2V1cmF0T2JqZWN0KQpsaWJyYXJ5KFNldXJhdERhdGEpCmxpYnJhcnkocGF0Y2h3b3JrKQpsaWJyYXJ5KGhhcm1vbnkpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjb3dwbG90KQpsaWJyYXJ5KHJldGljdWxhdGUpCmxpYnJhcnkoQXppbXV0aCkKbGlicmFyeShkcGx5cikKbGlicmFyeShSdHNuZSkKbGlicmFyeShoYXJtb255KQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCgpgYGAKCgojIDIuIExvYWQgU2V1cmF0IE9iamVjdCAKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMH0KCiNMb2FkIFNldXJhdCBPYmplY3QgbWVyZ2VkIGZyb20gY2VsbCBsaW5lcyBhbmQgYSBjb250cm9sIGFmdGVyIGZpbHRyYXRpb24KbG9hZCgiLi4vMC1yb2JqLzUtSGFybW9ueV9JbnRlZ3JhdGVkX0FsbF9zYW1wbGVzX01lcmdlZF9DRDRUY2VsbHNfZmluYWxfUmVzb2x1dGlvbl9TZWxlY3RlZF8wLjhfQURUX05vcm1hbGl6ZWRfY2xlYW5lZF9tdC5yb2JqIikKCmBgYAoKCiMgMy4gIFZpc3VsaXphdGlvbiBvZiBIYXJtb255IGludGVncmF0ZWQgT2JqZWN0CmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CkRlZmF1bHRBc3NheShBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJTQ1QiCgpEaW1QbG90KEFsbF9zYW1wbGVzX01lcmdlZCwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJzZXVyYXRfY2x1c3RlcnMiLCBsYWJlbCA9IFRSVUUsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gIm9yaWcuaWRlbnQiLCBsYWJlbCA9IFRSVUUsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCBncm91cC5ieSA9ICJwcmVkaWN0ZWQuY2VsbHR5cGUubDIiLCBsYWJlbCA9IEYpCgpgYGAKCiMgMy4gREUgQW5hbHlzaXMgVXNpbmcgUk5BIEFzc2F5IChMb2ctTm9ybWFsaXplZCBDb3VudHMpCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIFNldCB0aGUgZGVmYXVsdCBhc3NheSB0byBSTkEKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCiMgUGVyZm9ybSBMb2dOb3JtYWxpemF0aW9uIG9uIHRoZSBSTkEgYXNzYXkKQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIE5vcm1hbGl6ZURhdGEoQWxsX3NhbXBsZXNfTWVyZ2VkLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCBzY2FsZS5mYWN0b3IgPSAxMDAwMCkKCiMgU2V0IGlkZW50aXR5IGNsYXNzIHRvIGNlbGwgbGluZQpJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiY2VsbF9saW5lIgoKIyBEZWZpbmUgbWFsaWduYW50IGFuZCBub3JtYWwgY2VsbCBsaW5lcwptYWxpZ25hbnRfY2VsbF9saW5lIDwtIGMoIkwxIiwgIkwyIiwgIkwzIiwgIkw0IiwgIkw1IiwgIkw2IiwgIkw3IikgIApub3JtYWxfY2VsbF9saW5lIDwtIGMoIlBCTUMiLCAiUEJNQ18xMHgiKSAgCgojIFBlcmZvcm0gREUgYW5hbHlzaXMgdXNpbmcgUk5BIGFzc2F5CkRFX1JOQSA8LSBGaW5kTWFya2VycygKICBvYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQsIAogIGlkZW50LjEgPSBtYWxpZ25hbnRfY2VsbF9saW5lLAogIGlkZW50LjIgPSBub3JtYWxfY2VsbF9saW5lLAogIGFzc2F5ID0gIlJOQSIsICAgIyBVc2UgUk5BLW5vcm1hbGl6ZWQgY291bnRzCiAgbWluLnBjdCA9IDAsCiAgbG9nZmMudGhyZXNob2xkID0gMAopCgojIENvbnZlcnQgdG8gZGF0YSBmcmFtZSBhbmQgYWRkIGdlbmUgbmFtZXMKREVfUk5BIDwtIGFzLmRhdGEuZnJhbWUoREVfUk5BKQpERV9STkEkZ2VuZSA8LSByb3duYW1lcyhERV9STkEpCgojIFJlb3JkZXIgY29sdW1ucwpERV9STkEgPC0gREVfUk5BWywgYygiZ2VuZSIsICJwX3ZhbCIsICJhdmdfbG9nMkZDIiwgInBjdC4xIiwgInBjdC4yIiwgInBfdmFsX2FkaiIpXQoKIyBTYXZlIHJlc3VsdHMKd3JpdGUuY3N2KERFX1JOQSwgIk1hbGlnbmFudF9DRDRUY2VsbHNfdnNfTm9ybWFsX0NENFRjZWxsc19STkFfQXNzYXkuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgpgYGAKCiMgNC4gREUgQW5hbHlzaXMgVXNpbmcgU0NUIEFzc2F5IChTQ1RyYW5zZm9ybWVkIENvdW50cykKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgU2V0IHRoZSBkZWZhdWx0IGFzc2F5IHRvIFNDVApEZWZhdWx0QXNzYXkoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiU0NUIgoKIyBTZXQgaWRlbnRpdHkgY2xhc3MgdG8gY2VsbCBsaW5lCklkZW50cyhBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJjZWxsX2xpbmUiCgojIERlZmluZSBtYWxpZ25hbnQgYW5kIG5vcm1hbCBjZWxsIGxpbmVzCm1hbGlnbmFudF9jZWxsX2xpbmUgPC0gYygiTDEiLCAiTDIiLCAiTDMiLCAiTDQiLCAiTDUiLCAiTDYiLCAiTDciKSAgCm5vcm1hbF9jZWxsX2xpbmUgPC0gYygiUEJNQyIsICJQQk1DXzEweCIpICAKCiMgUGVyZm9ybSBERSBhbmFseXNpcyB1c2luZyBTQ1QgYXNzYXkKREVfU0NUIDwtIEZpbmRNYXJrZXJzKAogIG9iamVjdCA9IEFsbF9zYW1wbGVzX01lcmdlZCwgCiAgaWRlbnQuMSA9IG1hbGlnbmFudF9jZWxsX2xpbmUsCiAgaWRlbnQuMiA9IG5vcm1hbF9jZWxsX2xpbmUsCiAgYXNzYXkgPSAiU0NUIiwgICAjIFVzZSBTQ1Qtbm9ybWFsaXplZCBjb3VudHMKICBtaW4ucGN0ID0gMCwKICBsb2dmYy50aHJlc2hvbGQgPSAwCikKCiMgQ29udmVydCB0byBkYXRhIGZyYW1lIGFuZCBhZGQgZ2VuZSBuYW1lcwpERV9TQ1QgPC0gYXMuZGF0YS5mcmFtZShERV9TQ1QpCkRFX1NDVCRnZW5lIDwtIHJvd25hbWVzKERFX1NDVCkKCiMgUmVvcmRlciBjb2x1bW5zCkRFX1NDVCA8LSBERV9TQ1RbLCBjKCJnZW5lIiwgInBfdmFsIiwgImF2Z19sb2cyRkMiLCAicGN0LjEiLCAicGN0LjIiLCAicF92YWxfYWRqIildCgojIFNhdmUgcmVzdWx0cwp3cml0ZS5jc3YoREVfU0NULCAiTWFsaWduYW50X0NENFRjZWxsc192c19Ob3JtYWxfQ0Q0VGNlbGxzX1NDVF9TQ1RyYW5zZm9ybWVkLmNzdiIsIHJvdy5uYW1lcyA9IEZBTFNFKQoKCgpgYGAKCgojIDUuIERFIEFuYWx5c2lzIFZpc3VhbGl6ZSBSZXN1bHRzIG9mIFJOQSB2cyBTQ1QgY29tcGFyaXNvbl9hdmdfbG9nMkZDX1JOQQpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKbGlicmFyeShnZ3Bsb3QyKQpjb21tb25fZ2VuZXMgPC0gaW50ZXJzZWN0KERFX1JOQSRnZW5lLCBERV9TQ1QkZ2VuZSkKUk5BX3ZhbHVlcyA8LSBERV9STkFbREVfUk5BJGdlbmUgJWluJSBjb21tb25fZ2VuZXMsIF0KU0NUX3ZhbHVlcyA8LSBERV9TQ1RbREVfU0NUJGdlbmUgJWluJSBjb21tb25fZ2VuZXMsIF0KCmNvbXBhcmlzb25fZGYgPC0gbWVyZ2UoUk5BX3ZhbHVlcywgU0NUX3ZhbHVlcywgYnkgPSAiZ2VuZSIsIHN1ZmZpeGVzID0gYygiX1JOQSIsICJfU0NUIikpCmdncGxvdChjb21wYXJpc29uX2RmLCBhZXMoeCA9IGF2Z19sb2cyRkNfUk5BLCB5ID0gYXZnX2xvZzJGQ19TQ1QpKSArCiAgICBnZW9tX3BvaW50KCkgKwogICAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBjb2xvciA9ICJyZWQiKSArCiAgICB0aGVtZV9taW5pbWFsKCkgKwogICAgbGFicyh0aXRsZSA9ICJDb21wYXJpc29uIG9mIERFIFJlc3VsdHM6IFJOQSB2cyBTQ1QiLCB4ID0gIkxvZzJGQyAoUk5BKSIsIHkgPSAiTG9nMkZDIChTQ1QpIikKCmBgYAojIDYuIERFIEFuYWx5c2lzIFZpc3VhbGl6ZSBSZXN1bHRzIG9mIFJOQSB2cyBTQ1QgY29tcGFyaXNvbl9wX3ZhbF9hZGoKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCmxpYnJhcnkoZ2dwbG90MikKCiMgRmluZCBjb21tb24gZ2VuZXMgcHJlc2VudCBpbiBib3RoIERFIHJlc3VsdHMKY29tbW9uX2dlbmVzIDwtIGludGVyc2VjdChERV9STkEkZ2VuZSwgREVfU0NUJGdlbmUpCgojIEV4dHJhY3QgdGhlIHZhbHVlcyBmb3IgdGhlIGNvbW1vbiBnZW5lcwpSTkFfdmFsdWVzIDwtIERFX1JOQVtERV9STkEkZ2VuZSAlaW4lIGNvbW1vbl9nZW5lcywgXQpTQ1RfdmFsdWVzIDwtIERFX1NDVFtERV9TQ1QkZ2VuZSAlaW4lIGNvbW1vbl9nZW5lcywgXQoKIyBNZXJnZSBib3RoIGRhdGFzZXRzIG9uICJnZW5lIiBjb2x1bW4KY29tcGFyaXNvbl9kZiA8LSBtZXJnZShSTkFfdmFsdWVzLCBTQ1RfdmFsdWVzLCBieSA9ICJnZW5lIiwgc3VmZml4ZXMgPSBjKCJfUk5BIiwgIl9TQ1QiKSkKCiMgUGxvdCBhZGp1c3RlZCBwLXZhbHVlcyAobG9nLXRyYW5zZm9ybWVkIGZvciBiZXR0ZXIgdmlzdWFsaXphdGlvbikKZ2dwbG90KGNvbXBhcmlzb25fZGYsIGFlcyh4ID0gLWxvZzEwKHBfdmFsX2Fkal9STkEpLCB5ID0gLWxvZzEwKHBfdmFsX2Fkal9TQ1QpKSkgKwogICAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNSkgKyAgIyBUcmFuc3BhcmVuY3kgZm9yIGJldHRlciB2aXNpYmlsaXR5CiAgICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsgICMgRGlhZ29uYWwgcmVmZXJlbmNlIGxpbmUKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICBsYWJzKAogICAgICAgIHRpdGxlID0gIkNvbXBhcmlzb24gb2YgQWRqdXN0ZWQgcC12YWx1ZXM6IFJOQSB2cyBTQ1QiLAogICAgICAgIHggPSAiLWxvZzEwIEFkanVzdGVkIHAtdmFsdWUgKFJOQSkiLAogICAgICAgIHkgPSAiLWxvZzEwIEFkanVzdGVkIHAtdmFsdWUgKFNDVCkiCiAgICApICsKICAgIHRoZW1lKAogICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLCAgIyBDZW50ZXIgdGhlIHRpdGxlCiAgICAgICAgYXhpcy50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiksCiAgICAgICAgYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpCiAgICApCgoKYGBgCgoKKipXaHkgVXNlIE1BU1Q/CkhhbmRsZXMgemVybyBpbmZsYXRpb24gKGRyb3BvdXRzKSBpbiBzaW5nbGUtY2VsbCBSTkEtc2VxIGRhdGEuCkFjY291bnRzIGZvciB0ZWNobmljYWwgYW5kIGJpb2xvZ2ljYWwgdmFyaWF0aW9uLgpXb3JrcyB3ZWxsIHdoZW4gYWRqdXN0aW5nIGZvciBjb3ZhcmlhdGVzIChQYXRpZW50X29yaWdpbiAmIGNlbGxfbGluZSkuKioKCgojIDcuIERFIEFuYWx5c2lzIFVzaW5nIFJOQSBBc3NheSAoTG9nLU5vcm1hbGl6ZWQgQ291bnRzKSArIE1BU1QKYGBge3IgLCBmaWcuaGVpZ2h0PTgsIGZpZy53aWR0aD0xMn0KCiMgIyBMb2FkIHJlcXVpcmVkIHBhY2thZ2UgZm9yIE1BU1QKIyBsaWJyYXJ5KE1BU1QpCiMgCiMgIyBTZXQgdGhlIGRlZmF1bHQgYXNzYXkgdG8gUk5BCiMgRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKIyAKIyAjIFBlcmZvcm0gTG9nTm9ybWFsaXphdGlvbiBvbiB0aGUgUk5BIGFzc2F5CiMgQWxsX3NhbXBsZXNfTWVyZ2VkIDwtIE5vcm1hbGl6ZURhdGEoQWxsX3NhbXBsZXNfTWVyZ2VkLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJMb2dOb3JtYWxpemUiLCBzY2FsZS5mYWN0b3IgPSAxMDAwMCkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCkRlZmF1bHRBc3NheShBbGxfc2FtcGxlc19NZXJnZWQpIDwtICJSTkEiCgojIFNldCBpZGVudGl0eSBjbGFzcyB0byBjZWxsIGxpbmUKSWRlbnRzKEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gImNlbGxfbGluZSIKCiMgRGVmaW5lIG1hbGlnbmFudCBhbmQgbm9ybWFsIGNlbGwgbGluZXMKbWFsaWduYW50X2NlbGxfbGluZV9MMSA8LSBjKCJMMSIpICAKbm9ybWFsX0NENFRjZWxscyA8LSBjKCJQQk1DIiwgIlBCTUNfMTB4IikgIAoKIyBQZXJmb3JtIERFIGFuYWx5c2lzIHVzaW5nIFJOQSBhc3NheSB3aXRoIE1BU1QgYW5kIGNvdmFyaWF0ZXMKREVfUk5BX01BU1QgPC0gRmluZE1hcmtlcnMoCiAgb2JqZWN0ID0gQWxsX3NhbXBsZXNfTWVyZ2VkLCAKICBpZGVudC4xID0gbWFsaWduYW50X2NlbGxfbGluZV9MMSwKICBpZGVudC4yID0gbm9ybWFsX0NENFRjZWxscywKICBhc3NheSA9ICJSTkEiLCAgICMgVXNlIFJOQS1ub3JtYWxpemVkIGNvdW50cwogIHRlc3QudXNlID0gIk1BU1QiLCAgIyBVc2UgTUFTVCB0ZXN0CiAgbWluLnBjdCA9IDAsCiAgbG9nZmMudGhyZXNob2xkID0gMCwKICBsYXRlbnQudmFycyA9IGMoIlBhdGllbnRfb3JpZ2luIiwgImNlbGxfbGluZSIpICAjIEFkanVzdCBmb3IgcGF0aWVudCBhbmQgY2VsbCBsaW5lCikKCiMgQ29udmVydCB0byBkYXRhIGZyYW1lIGFuZCBhZGQgZ2VuZSBuYW1lcwpERV9STkFfTUFTVCA8LSBhcy5kYXRhLmZyYW1lKERFX1JOQV9NQVNUKQpERV9STkFfTUFTVCRnZW5lIDwtIHJvd25hbWVzKERFX1JOQV9NQVNUKQoKIyBSZW9yZGVyIGNvbHVtbnMKREVfUk5BX01BU1QgPC0gREVfUk5BX01BU1RbLCBjKCJnZW5lIiwgInBfdmFsIiwgImF2Z19sb2cyRkMiLCAicGN0LjEiLCAicGN0LjIiLCAicF92YWxfYWRqIildCgojIFNhdmUgcmVzdWx0cwp3cml0ZS5jc3YoREVfUk5BX01BU1QsICJNYWxpZ25hbnRfQ0Q0VGNlbGxzX0wxX3ZzX05vcm1hbF9DRDRUY2VsbHNfUk5BX01BU1QuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpCgoKCmBgYAoKCiMgOC4gREUgQW5hbHlzaXMgVXNpbmcgU0NUIEFzc2F5IChTQ1RyYW5zZm9ybWVkIENvdW50cykgKyBNQVNUCmBgYHtyICwgZmlnLmhlaWdodD04LCBmaWcud2lkdGg9MTJ9CgojIExvYWQgcmVxdWlyZWQgcGFja2FnZSBmb3IgTUFTVApsaWJyYXJ5KE1BU1QpCgojIFNldCB0aGUgZGVmYXVsdCBhc3NheSB0byBTQ1QKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlNDVCIKCiMgU2V0IGlkZW50aXR5IGNsYXNzIHRvIGNlbGwgbGluZQpJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAiY2VsbF9saW5lIgoKIyBEZWZpbmUgbWFsaWduYW50IGFuZCBub3JtYWwgY2VsbCBsaW5lcwptYWxpZ25hbnRfY2VsbF9saW5lX0wxIDwtIGMoIkwxIikgIApub3JtYWxfQ0Q0VGNlbGxzIDwtIGMoIlBCTUMiLCAiUEJNQ18xMHgiKSAgCgojIFBlcmZvcm0gREUgYW5hbHlzaXMgdXNpbmcgU0NUIGFzc2F5IHdpdGggTUFTVCBhbmQgY292YXJpYXRlcwpERV9TQ1RfTUFTVCA8LSBGaW5kTWFya2VycygKICBvYmplY3QgPSBBbGxfc2FtcGxlc19NZXJnZWQsIAogIGlkZW50LjEgPSBtYWxpZ25hbnRfY2VsbF9saW5lX0wxLAogIGlkZW50LjIgPSBub3JtYWxfQ0Q0VGNlbGxzLAogIGFzc2F5ID0gIlNDVCIsICAgIyBVc2UgU0NULW5vcm1hbGl6ZWQgY291bnRzCiAgdGVzdC51c2UgPSAiTUFTVCIsICAjIFVzZSBNQVNUIHRlc3QKICBtaW4ucGN0ID0gMCwKICBsb2dmYy50aHJlc2hvbGQgPSAwLAogIGxhdGVudC52YXJzID0gYygiUGF0aWVudF9vcmlnaW4iLCAiY2VsbF9saW5lIikgICMgQWRqdXN0IGZvciBwYXRpZW50IGFuZCBjZWxsIGxpbmUKKQoKIyBDb252ZXJ0IHRvIGRhdGEgZnJhbWUgYW5kIGFkZCBnZW5lIG5hbWVzCkRFX1NDVF9NQVNUIDwtIGFzLmRhdGEuZnJhbWUoREVfU0NUX01BU1QpCkRFX1NDVF9NQVNUJGdlbmUgPC0gcm93bmFtZXMoREVfU0NUX01BU1QpCgojIFJlb3JkZXIgY29sdW1ucwpERV9TQ1RfTUFTVCA8LSBERV9TQ1RfTUFTVFssIGMoImdlbmUiLCAicF92YWwiLCAiYXZnX2xvZzJGQyIsICJwY3QuMSIsICJwY3QuMiIsICJwX3ZhbF9hZGoiKV0KCiMgU2F2ZSByZXN1bHRzCndyaXRlLmNzdihERV9TQ1RfTUFTVCwgIk1hbGlnbmFudF9DRDRUY2VsbHNfTDFfdnNfTm9ybWFsX0NENFRjZWxsc19TQ1RfTUFTVC5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkKCgpgYGAKCgojIDkuIERFIEFuYWx5c2lzIFZpc3VhbGl6ZSBSZXN1bHRzIG9mIFJOQSB2cyBTQ1QgY29tcGFyaXNvbl9hdmdfbG9nMkZDX1JOQQpgYGB7ciAsIGZpZy5oZWlnaHQ9OCwgZmlnLndpZHRoPTEyfQoKIyBMb2FkIHJlcXVpcmVkIGxpYnJhcmllcwpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZ2dyZXBlbCkgICMgRm9yIGJldHRlciBsYWJlbGluZyBvZiBvdXRsaWVyIGdlbmVzCgojIExvYWQgREUgcmVzdWx0cwpERV9STkFfTUFTVCA8LSByZWFkLmNzdigiTWFsaWduYW50X0NENFRjZWxsc19MMV92c19Ob3JtYWxfQ0Q0VGNlbGxzX1JOQV9NQVNULmNzdiIpCkRFX1NDVF9NQVNUIDwtIHJlYWQuY3N2KCJNYWxpZ25hbnRfQ0Q0VGNlbGxzX0wxX3ZzX05vcm1hbF9DRDRUY2VsbHNfU0NUX01BU1QuY3N2IikKCiMgRmluZCBjb21tb24gZ2VuZXMgaW4gYm90aCBkYXRhc2V0cwpjb21tb25fZ2VuZXMgPC0gaW50ZXJzZWN0KERFX1JOQV9NQVNUJGdlbmUsIERFX1NDVF9NQVNUJGdlbmUpCgojIEZpbHRlciBmb3IgY29tbW9uIGdlbmVzClJOQV92YWx1ZXMgPC0gREVfUk5BX01BU1RbREVfUk5BX01BU1QkZ2VuZSAlaW4lIGNvbW1vbl9nZW5lcywgXQpTQ1RfdmFsdWVzIDwtIERFX1NDVF9NQVNUW0RFX1NDVF9NQVNUJGdlbmUgJWluJSBjb21tb25fZ2VuZXMsIF0KCiMgTWVyZ2UgZGF0YXNldHMKY29tcGFyaXNvbl9kZiA8LSBtZXJnZShSTkFfdmFsdWVzLCBTQ1RfdmFsdWVzLCBieSA9ICJnZW5lIiwgc3VmZml4ZXMgPSBjKCJfUk5BIiwgIl9TQ1QiKSkKCiMgLS0tLSBQTE9UIDE6IExvZzIgRm9sZCBDaGFuZ2UgKExvZzJGQykgQ29tcGFyaXNvbiAtLS0tCnAxIDwtIGdncGxvdChjb21wYXJpc29uX2RmLCBhZXMoeCA9IGF2Z19sb2cyRkNfUk5BLCB5ID0gYXZnX2xvZzJGQ19TQ1QpKSArCiAgICBnZW9tX3BvaW50KGFscGhhID0gMC41KSArCiAgICBnZW9tX2FibGluZShzbG9wZSA9IDEsIGludGVyY2VwdCA9IDAsIGNvbG9yID0gInJlZCIsIGxpbmV0eXBlID0gImRhc2hlZCIpICsgICMgRGlhZ29uYWwgcmVmZXJlbmNlIGxpbmUKICAgIHRoZW1lX21pbmltYWwoKSArCiAgICBsYWJzKHRpdGxlID0gIkxvZzIgRm9sZCBDaGFuZ2UgKExvZzJGQykgQ29tcGFyaXNvbjogUk5BIHZzIFNDVCAoTUFTVCkiLAogICAgICAgICB4ID0gIkxvZzIgRm9sZCBDaGFuZ2UgKFJOQSkiLAogICAgICAgICB5ID0gIkxvZzIgRm9sZCBDaGFuZ2UgKFNDVCkiKSArCiAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkKCiMgLS0tLSBQTE9UIDI6IEFkanVzdGVkIHAtdmFsdWUgKHBfdmFsX2FkaikgQ29tcGFyaXNvbiAtLS0tCnAyIDwtIGdncGxvdChjb21wYXJpc29uX2RmLCBhZXMoeCA9IC1sb2cxMChwX3ZhbF9hZGpfUk5BKSwgeSA9IC1sb2cxMChwX3ZhbF9hZGpfU0NUKSkpICsKICAgIGdlb21fcG9pbnQoYWxwaGEgPSAwLjUpICsKICAgIGdlb21fYWJsaW5lKHNsb3BlID0gMSwgaW50ZXJjZXB0ID0gMCwgY29sb3IgPSAicmVkIiwgbGluZXR5cGUgPSAiZGFzaGVkIikgKyAgIyBSZWZlcmVuY2UgbGluZQogICAgdGhlbWVfbWluaW1hbCgpICsKICAgIGxhYnModGl0bGUgPSAiQWRqdXN0ZWQgcC12YWx1ZSAoLWxvZzEwKSBDb21wYXJpc29uOiBSTkEgdnMgU0NUIChNQVNUKSIsCiAgICAgICAgIHggPSAiLWxvZzEwIEFkanVzdGVkIHAtdmFsdWUgKFJOQSkiLAogICAgICAgICB5ID0gIi1sb2cxMCBBZGp1c3RlZCBwLXZhbHVlIChTQ1QpIikgKwogICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpCgojIC0tLS0gUExPVCBCT1RIIC0tLS0KbGlicmFyeShncmlkRXh0cmEpCmdyaWQuYXJyYW5nZShwMSwgcDIsIG5jb2wgPSAyKQoKCmBgYAoKCg==