1. Load Libraries
2. load seurat object
#Load Seurat Object L7
load("../0-robj/5-Harmony_Integrated_All_samples_Merged_CD4Tcells_final_Resolution_Selected_0.8_ADT_Normalized_cleaned_mt.robj")
All_samples_Merged
3. Set Up Identifiers for Clustering
# Assign cluster identities to the Seurat object
Idents(All_samples_Merged) <- "seurat_clusters"
DimPlot(All_samples_Merged, reduction = "umap", group.by = "cell_line",label = T, label.box = T)

DimPlot(All_samples_Merged, reduction = "umap", group.by = "seurat_clusters",label = T, label.box = T)

4. Differential Expression Analysis
4.1 Using MAST with SCT and Latent Variables (Batch Correction)
markers_mast_SCT <- FindMarkers(
All_samples_Merged,
ident.1 = c("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13"), # Cell lines-Malignant
ident.2 = c("3", "10"), # Normal CD4 T cells
assay = "SCT",
test.use = "MAST",
latent.vars = c("cell_line", "Patient_origin"), # Adjust for batch effects
min.pct = 0,
logfc.threshold = 0
)
write.csv(markers_mast_SCT, file = "../0-robj/1-MAST_with_SCT_batch_patient_cellline_as_Covariate.csv", row.names = TRUE)
4.2 Using MAST with RNA and Latent Variables (Batch Correction)
markers_mast_RNA <- FindMarkers(
All_samples_Merged,
ident.1 = cc("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13"), # Cell lines-Malignant
ident.2 = c("3", "10"), # Normal CD4 T cells
assay = "RNA",
test.use = "MAST",
latent.vars = c("cell_line", "Patient_origin"), # Adjust for batch effects
min.pct = 0,
logfc.threshold = 0
)
Erreur dans cc("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13") :
impossible de trouver la fonction "cc"
5. Compute Mean Expression for Groups
library(Seurat)
library(dplyr)
# Define cell groups
group1_cells <- WhichCells(All_samples_Merged, idents = c("5", "9", "1", "2", "6", "8", "4", "0", "7", "11", "12", "13")) # Malignant CD4+ T cells
group2_cells <- WhichCells(All_samples_Merged, idents = c("3", "10")) # Normal CD4+ T cells
# Extract normalized expression values for both assays
expression_data_RNA <- GetAssayData(All_samples_Merged, assay = "RNA", layer = "data") # Log-normalized counts
expression_data_SCT <- GetAssayData(All_samples_Merged, assay = "SCT", layer = "data") # SCT-normalized counts (not Pearson residuals)
# Function to calculate mean expression for each group
calculate_mean_expression <- function(markers, group1_cells, group2_cells, expression_data) {
group1_mean <- rowMeans(expression_data[, group1_cells, drop = FALSE], na.rm = TRUE)
group2_mean <- rowMeans(expression_data[, group2_cells, drop = FALSE], na.rm = TRUE)
markers <- markers %>%
rownames_to_column("gene") %>%
mutate(mean_expr_group1 = group1_mean[gene],
mean_expr_group2 = group2_mean[gene])
return(markers)
}
# Compute mean expression for RNA and SCT assays
markers_mast_RNA <- calculate_mean_expression(markers_mast_RNA, group1_cells, group2_cells, expression_data_RNA)
markers_mast_SCT <- calculate_mean_expression(markers_mast_SCT, group1_cells, group2_cells, expression_data_SCT)
# Save updated results with mean expression
write.csv(markers_mast_RNA, file = "../0-robj/2-MAST_with_RNA_batch_patient_cellline_as_Covariate_with_meanExpression.csv", row.names = TRUE)
write.csv(markers_mast_SCT, file = "../0-robj/1-MAST_with_SCT_batch_patient_cellline_as_Covariate_with_meanExpression.csv", row.names = TRUE)
6. Summarize Results
6.1 Summary Function
summarize_markers <- function(markers) {
num_pval0 <- sum(markers$p_val_adj == 0)
num_pval1 <- sum(markers$p_val_adj == 1)
num_significant <- sum(markers$p_val_adj < 0.05)
num_upregulated <- sum(markers$avg_log2FC > 1)
num_downregulated <- sum(markers$avg_log2FC < -1)
cat("Number of genes with p_val_adj = 0:", num_pval0, "\n")
cat("Number of genes with p_val_adj = 1:", num_pval1, "\n")
cat("Number of significant genes (p_val_adj < 0.05):", num_significant, "\n")
cat("Number of upregulated genes (avg_log2FC > 1):", num_upregulated, "\n")
cat("Number of downregulated genes (avg_log2FC < -1):", num_downregulated, "\n")
}
6.2 Summarize Markers1 (MAST with SCT Assay)
cat("Markers1 Summary (MAST with SCT Assay):\n")
Markers1 Summary (MAST with SCT Assay):
summarize_markers(markers_mast_SCT)
Number of genes with p_val_adj = 0: 74
Number of genes with p_val_adj = 1: 19337
Number of significant genes (p_val_adj < 0.05): 5615
Number of upregulated genes (avg_log2FC > 1): 15048
Number of downregulated genes (avg_log2FC < -1): 2281
6.3 Summary for Markers2 (MAST with RNA Assay)
cat("Markers2 Summary (MAST with RNA Assay):\n")
Markers2 Summary (MAST with RNA Assay):
summarize_markers(markers_mast_RNA)
Number of genes with p_val_adj = 0: 83
Number of genes with p_val_adj = 1: 26400
Number of significant genes (p_val_adj < 0.05): 9221
Number of upregulated genes (avg_log2FC > 1): 7334
Number of downregulated genes (avg_log2FC < -1): 15426
Compare Results Between SCT and RNA Assays
### Compare Results Between RNA and SCT Assays
# Load gene sets
genes_mast_sct <- markers_mast_SCT$gene
genes_mast_rna <- markers_mast_RNA$gene
common_genes_mast <- intersect(genes_mast_sct, genes_mast_rna)
cat("MAST: Common Genes Between SCT and RNA:", length(common_genes_mast), "\n")
MAST: Common Genes Between SCT and RNA: 26176
7. Visualization
7.1 Volcano Plot for MAST-SCT with Batch Correction
EnhancedVolcano(markers_mast_SCT,
lab = markers_mast_SCT$gene,
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant_vs_Normal_MAST_SCT",
pCutoff = 0.05,
FCcutoff = 1.0)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

7.2 Volcano Plot MAST-RNA with Batch Correction
EnhancedVolcano(markers_mast_RNA,
lab = markers_mast_RNA$gene,
x = "avg_log2FC",
y = "p_val_adj",
title = "Malignant_vs_Normal_MAST_RNA",
pCutoff = 0.05,
FCcutoff = 1.0)
Avis : One or more p-values is 0. Converting to 10^-1 * current lowest non-zero p-value...

7.3 Volcano Plot MAST-RNA with Batch Correction
### 1. Load Data and Prepare for Comparison
library(ggplot2)
df_sct <- read.csv("../0-robj/1-MAST_with_SCT_batch_patient_cellline_as_Covariate.csv", row.names = 1)
df_rna <- read.csv("../0-robj/2-MAST_with_RNA_batch_patient_cellline_as_Covariate.csv", row.names = 1)
df_sct$assay <- "SCT"
df_rna$assay <- "RNA"
df_combined <- rbind(df_sct, df_rna)
### 2. Volcano Plot for SCT vs RNA Comparison
ggplot(df_combined, aes(x = avg_log2FC, y = -log10(p_val_adj), color = assay)) +
geom_point(alpha = 0.7) +
theme_minimal() +
labs(title = "Volcano Plot: RNA vs SCT", x = "Log2 Fold Change", y = "-Log10 Adjusted P-value") +
scale_color_manual(values = c("SCT" = "blue", "RNA" = "red"))

7.4 Correlation of Log2 Fold Change Between RNA and SCT
# Correlation of Log2 Fold Change Between RNA and SCT
# Goal: See if genes have consistent fold changes between RNA and SCT normalization.
library(dplyr) # Load dplyr to use rownames_to_column
# Convert row names to a "gene" column
df_sct <- df_sct %>% rownames_to_column(var = "gene")
df_rna <- df_rna %>% rownames_to_column(var = "gene")
# Merge datasets by gene
df_merged <- merge(df_sct, df_rna, by = "gene", suffixes = c("_SCT", "_RNA"))
# Scatter plot of log2FC values
ggplot(df_merged, aes(x = avg_log2FC_SCT, y = avg_log2FC_RNA)) +
geom_point(alpha = 0.7, color = "blue") +
geom_smooth(method = "lm", color = "red", linetype = "dashed") +
theme_minimal() +
labs(title = "Log2 Fold Change Comparison: SCT vs RNA",
x = "SCT Log2 Fold Change",
y = "RNA Log2 Fold Change") +
geom_abline(slope = 1, intercept = 0, linetype = "dotted", color = "black")

7.5 Find overlap between the top 100 most significant genes:
cor(df_merged$avg_log2FC_SCT, df_merged$avg_log2FC_RNA, use = "complete.obs")
[1] 0.9815925
# Higher correlation (~0.8-1.0) suggests consistency between methods.
# Lower correlation (<0.6) may indicate different normalization effects.
library(ggplot2)
library(dplyr)
# Define a broader list of known Sezary genes
sezary_genes <- c("KIR3DL2", "TOX", "TWIST1", "CD52", "CCR4", "IL2RA", "CD7", "DPP4", "CCR7", "GATA3", "FOXP3", "CD8A", "CD4", "CYP27B1", "TET2")
# Filter the merged data to include only the known Sezary genes
df_filtered <- df_merged %>%
filter(gene %in% sezary_genes)
# Volcano plot showing only the known Sezary genes with gene names
ggplot(df_filtered, aes(x = avg_log2FC_SCT, y = -log10(p_val_adj_SCT), color = gene)) +
geom_point(alpha = 0.7) +
geom_text(aes(label = gene), vjust = 1.5, hjust = 0.5, size = 3, color = "black") + # Adding gene names
theme_minimal() +
labs(title = "Volcano Plot: Known Sezary Genes (SCT Assay)",
x = "Log2 Fold Change (SCT)",
y = "-Log10 Adjusted P-value") +
scale_color_manual(values = c("KIR3DL2" = "#1f77b4", # blue
"TOX" = "#ff7f0e", # orange
"TWIST1" = "#2ca02c", # green
"CD52" = "#9467bd", # purple
"CCR4" = "#8c564b", # brown
"IL2RA" = "#e377c2", # pink
"CD7" = "#7f7f7f", # gray
"DPP4" = "#bcbd22", # yellow-green
"CCR7" = "#17becf", # cyan
"GATA3" = "#d62728", # red
"FOXP3" = "#8a2be2", # blue-violet
"CD8A" = "#ff6347", # tomato
"CD4" = "#3cb371", # medium sea green
"CYP27B1" = "#ff1493", # deep pink
"TET2" = "#00bfff")) + # deep sky blue
theme(legend.position = "top")

LS0tCnRpdGxlOiAiTUFTVCBvbiBTQ1QgYW5kIFJOQSBhc3NheSBhbmQgaXRzIGNvbXBhcmlzb24gdG8gc2VlIHdoaWNoIGlzIGJldHRlciIKYXV0aG9yOiAiTmFzaXIgTWFobW9vZCBBYmJhc2kiCmRhdGU6ICJgciBTeXMuRGF0ZSgpYCIKb3V0cHV0OgogIGh0bWxfbm90ZWJvb2s6CiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICAgIHRvY19jb2xsYXBzZWQ6IHllcwogIHBkZl9kb2N1bWVudDoKICAgIHRvYzogeWVzCi0tLQoKIyAxLiBMb2FkIExpYnJhcmllcwpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0KbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoaGFybW9ueSkKbGlicmFyeShkcGx5cikKbGlicmFyeShFbmhhbmNlZFZvbGNhbm8pCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeSh0aWJibGUpCmBgYAoKCiMgMi4gbG9hZCBzZXVyYXQgb2JqZWN0CmBgYHtyIGxvYWRfc2V1cmF0fQojTG9hZCBTZXVyYXQgT2JqZWN0IEw3CmxvYWQoIi4uLzAtcm9iai81LUhhcm1vbnlfSW50ZWdyYXRlZF9BbGxfc2FtcGxlc19NZXJnZWRfQ0Q0VGNlbGxzX2ZpbmFsX1Jlc29sdXRpb25fU2VsZWN0ZWRfMC44X0FEVF9Ob3JtYWxpemVkX2NsZWFuZWRfbXQucm9iaiIpCgoKQWxsX3NhbXBsZXNfTWVyZ2VkCgoKCmBgYAoKIyAzLiBTZXQgVXAgSWRlbnRpZmllcnMgZm9yIENsdXN0ZXJpbmcKYGBge3J9CiMgQXNzaWduIGNsdXN0ZXIgaWRlbnRpdGllcyB0byB0aGUgU2V1cmF0IG9iamVjdApJZGVudHMoQWxsX3NhbXBsZXNfTWVyZ2VkKSA8LSAic2V1cmF0X2NsdXN0ZXJzIgoKRGltUGxvdChBbGxfc2FtcGxlc19NZXJnZWQsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiY2VsbF9saW5lIixsYWJlbCA9IFQsIGxhYmVsLmJveCA9IFQpCkRpbVBsb3QoQWxsX3NhbXBsZXNfTWVyZ2VkLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gInNldXJhdF9jbHVzdGVycyIsbGFiZWwgPSBULCBsYWJlbC5ib3ggPSBUKQoKYGBgCgojIDQuICBEaWZmZXJlbnRpYWwgRXhwcmVzc2lvbiBBbmFseXNpcwoKIyMgNC4xIFVzaW5nIE1BU1Qgd2l0aCBTQ1QgYW5kIExhdGVudCBWYXJpYWJsZXMgKEJhdGNoIENvcnJlY3Rpb24pCmBgYHtyfQptYXJrZXJzX21hc3RfU0NUIDwtIEZpbmRNYXJrZXJzKAogIEFsbF9zYW1wbGVzX01lcmdlZCwKICBpZGVudC4xID0gYygiNSIsICI5IiwgIjEiLCAiMiIsICI2IiwgIjgiLCAiNCIsICIwIiwgIjciLCAiMTEiLCAiMTIiLCAiMTMiKSwgIyBDZWxsIGxpbmVzLU1hbGlnbmFudAogIGlkZW50LjIgPSBjKCIzIiwgIjEwIiksICMgTm9ybWFsIENENCBUIGNlbGxzCiAgYXNzYXkgPSAiU0NUIiwKICB0ZXN0LnVzZSA9ICJNQVNUIiwKICBsYXRlbnQudmFycyA9IGMoImNlbGxfbGluZSIsICJQYXRpZW50X29yaWdpbiIpLCAjIEFkanVzdCBmb3IgYmF0Y2ggZWZmZWN0cwogIG1pbi5wY3QgPSAwLAogIGxvZ2ZjLnRocmVzaG9sZCA9IDAKKQp3cml0ZS5jc3YobWFya2Vyc19tYXN0X1NDVCwgZmlsZSA9ICIuLi8wLXJvYmovMS1NQVNUX3dpdGhfU0NUX2JhdGNoX3BhdGllbnRfY2VsbGxpbmVfYXNfQ292YXJpYXRlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKIyMgNC4yIFVzaW5nIE1BU1Qgd2l0aCBSTkEgYW5kIExhdGVudCBWYXJpYWJsZXMgKEJhdGNoIENvcnJlY3Rpb24pCmBgYHtyfQoKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkobWFncml0dHIpCgojIFNldCB0aGUgZGVmYXVsdCBhc3NheSB0byBSTkEKRGVmYXVsdEFzc2F5KEFsbF9zYW1wbGVzX01lcmdlZCkgPC0gIlJOQSIKCiMgTm9ybWFsaXplIHRoZSBSTkEgYXNzYXkgYnV0IERPIE5PVCBzY2FsZSB0aGUgZGF0YQpBbGxfc2FtcGxlc19NZXJnZWQgPC0gQWxsX3NhbXBsZXNfTWVyZ2VkICU+JQogIE5vcm1hbGl6ZURhdGEobm9ybWFsaXphdGlvbi5tZXRob2QgPSAiTG9nTm9ybWFsaXplIiwgc2NhbGUuZmFjdG9yID0gMTAwMDApCgoKbWFya2Vyc19tYXN0X1JOQSA8LSBGaW5kTWFya2VycygKICBBbGxfc2FtcGxlc19NZXJnZWQsCiBpZGVudC4xID0gYygiNSIsICI5IiwgIjEiLCAiMiIsICI2IiwgIjgiLCAiNCIsICIwIiwgIjciLCAiMTEiLCAiMTIiLCAiMTMiKSwgIyBDZWxsIGxpbmVzLU1hbGlnbmFudAogIGlkZW50LjIgPSBjKCIzIiwgIjEwIiksICMgTm9ybWFsIENENCBUIGNlbGxzCiAgYXNzYXkgPSAiUk5BIiwKICB0ZXN0LnVzZSA9ICJNQVNUIiwKICBsYXRlbnQudmFycyA9IGMoImNlbGxfbGluZSIsICJQYXRpZW50X29yaWdpbiIpLCAjIEFkanVzdCBmb3IgYmF0Y2ggZWZmZWN0cwogIG1pbi5wY3QgPSAwLAogIGxvZ2ZjLnRocmVzaG9sZCA9IDAKKQp3cml0ZS5jc3YobWFya2Vyc19tYXN0X1JOQSwgZmlsZSA9ICIuLi8wLXJvYmovMi1NQVNUX3dpdGhfUk5BX2JhdGNoX3BhdGllbnRfY2VsbGxpbmVfYXNfQ292YXJpYXRlLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCmBgYAoKCgojIDUuIENvbXB1dGUgTWVhbiBFeHByZXNzaW9uIGZvciBHcm91cHMKYGBge3J9CmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGRwbHlyKQoKIyBEZWZpbmUgY2VsbCBncm91cHMKZ3JvdXAxX2NlbGxzIDwtIFdoaWNoQ2VsbHMoQWxsX3NhbXBsZXNfTWVyZ2VkLCBpZGVudHMgPSBjKCI1IiwgIjkiLCAiMSIsICIyIiwgIjYiLCAiOCIsICI0IiwgIjAiLCAiNyIsICIxMSIsICIxMiIsICIxMyIpKSAgIyBNYWxpZ25hbnQgQ0Q0KyBUIGNlbGxzCmdyb3VwMl9jZWxscyA8LSBXaGljaENlbGxzKEFsbF9zYW1wbGVzX01lcmdlZCwgaWRlbnRzID0gYygiMyIsICIxMCIpKSAgIyBOb3JtYWwgQ0Q0KyBUIGNlbGxzCgojIEV4dHJhY3Qgbm9ybWFsaXplZCBleHByZXNzaW9uIHZhbHVlcyBmb3IgYm90aCBhc3NheXMKZXhwcmVzc2lvbl9kYXRhX1JOQSA8LSBHZXRBc3NheURhdGEoQWxsX3NhbXBsZXNfTWVyZ2VkLCBhc3NheSA9ICJSTkEiLCBsYXllciA9ICJkYXRhIikgICMgTG9nLW5vcm1hbGl6ZWQgY291bnRzCmV4cHJlc3Npb25fZGF0YV9TQ1QgPC0gR2V0QXNzYXlEYXRhKEFsbF9zYW1wbGVzX01lcmdlZCwgYXNzYXkgPSAiU0NUIiwgbGF5ZXIgPSAiZGF0YSIpICAjIFNDVC1ub3JtYWxpemVkIGNvdW50cyAobm90IFBlYXJzb24gcmVzaWR1YWxzKQoKIyBGdW5jdGlvbiB0byBjYWxjdWxhdGUgbWVhbiBleHByZXNzaW9uIGZvciBlYWNoIGdyb3VwCmNhbGN1bGF0ZV9tZWFuX2V4cHJlc3Npb24gPC0gZnVuY3Rpb24obWFya2VycywgZ3JvdXAxX2NlbGxzLCBncm91cDJfY2VsbHMsIGV4cHJlc3Npb25fZGF0YSkgewogIGdyb3VwMV9tZWFuIDwtIHJvd01lYW5zKGV4cHJlc3Npb25fZGF0YVssIGdyb3VwMV9jZWxscywgZHJvcCA9IEZBTFNFXSwgbmEucm0gPSBUUlVFKQogIGdyb3VwMl9tZWFuIDwtIHJvd01lYW5zKGV4cHJlc3Npb25fZGF0YVssIGdyb3VwMl9jZWxscywgZHJvcCA9IEZBTFNFXSwgbmEucm0gPSBUUlVFKQogIAogIG1hcmtlcnMgPC0gbWFya2VycyAlPiUKICAgIHJvd25hbWVzX3RvX2NvbHVtbigiZ2VuZSIpICU+JQogICAgbXV0YXRlKG1lYW5fZXhwcl9ncm91cDEgPSBncm91cDFfbWVhbltnZW5lXSwKICAgICAgICAgICBtZWFuX2V4cHJfZ3JvdXAyID0gZ3JvdXAyX21lYW5bZ2VuZV0pCiAgCiAgcmV0dXJuKG1hcmtlcnMpCn0KCiMgQ29tcHV0ZSBtZWFuIGV4cHJlc3Npb24gZm9yIFJOQSBhbmQgU0NUIGFzc2F5cwptYXJrZXJzX21hc3RfUk5BIDwtIGNhbGN1bGF0ZV9tZWFuX2V4cHJlc3Npb24obWFya2Vyc19tYXN0X1JOQSwgZ3JvdXAxX2NlbGxzLCBncm91cDJfY2VsbHMsIGV4cHJlc3Npb25fZGF0YV9STkEpCm1hcmtlcnNfbWFzdF9TQ1QgPC0gY2FsY3VsYXRlX21lYW5fZXhwcmVzc2lvbihtYXJrZXJzX21hc3RfU0NULCBncm91cDFfY2VsbHMsIGdyb3VwMl9jZWxscywgZXhwcmVzc2lvbl9kYXRhX1NDVCkKCiMgU2F2ZSB1cGRhdGVkIHJlc3VsdHMgd2l0aCBtZWFuIGV4cHJlc3Npb24Kd3JpdGUuY3N2KG1hcmtlcnNfbWFzdF9STkEsIGZpbGUgPSAiLi4vMC1yb2JqLzItTUFTVF93aXRoX1JOQV9iYXRjaF9wYXRpZW50X2NlbGxsaW5lX2FzX0NvdmFyaWF0ZV93aXRoX21lYW5FeHByZXNzaW9uLmNzdiIsIHJvdy5uYW1lcyA9IFRSVUUpCndyaXRlLmNzdihtYXJrZXJzX21hc3RfU0NULCBmaWxlID0gIi4uLzAtcm9iai8xLU1BU1Rfd2l0aF9TQ1RfYmF0Y2hfcGF0aWVudF9jZWxsbGluZV9hc19Db3ZhcmlhdGVfd2l0aF9tZWFuRXhwcmVzc2lvbi5jc3YiLCByb3cubmFtZXMgPSBUUlVFKQoKYGBgCgojIDYuIFN1bW1hcml6ZSBSZXN1bHRzCgojIyA2LjEgU3VtbWFyeSBGdW5jdGlvbgpgYGB7cn0Kc3VtbWFyaXplX21hcmtlcnMgPC0gZnVuY3Rpb24obWFya2VycykgewogIG51bV9wdmFsMCA8LSBzdW0obWFya2VycyRwX3ZhbF9hZGogPT0gMCkKICBudW1fcHZhbDEgPC0gc3VtKG1hcmtlcnMkcF92YWxfYWRqID09IDEpCiAgbnVtX3NpZ25pZmljYW50IDwtIHN1bShtYXJrZXJzJHBfdmFsX2FkaiA8IDAuMDUpCiAgbnVtX3VwcmVndWxhdGVkIDwtIHN1bShtYXJrZXJzJGF2Z19sb2cyRkMgPiAxKQogIG51bV9kb3ducmVndWxhdGVkIDwtIHN1bShtYXJrZXJzJGF2Z19sb2cyRkMgPCAtMSkKICAKICBjYXQoIk51bWJlciBvZiBnZW5lcyB3aXRoIHBfdmFsX2FkaiA9IDA6IiwgbnVtX3B2YWwwLCAiXG4iKQogIGNhdCgiTnVtYmVyIG9mIGdlbmVzIHdpdGggcF92YWxfYWRqID0gMToiLCBudW1fcHZhbDEsICJcbiIpCiAgY2F0KCJOdW1iZXIgb2Ygc2lnbmlmaWNhbnQgZ2VuZXMgKHBfdmFsX2FkaiA8IDAuMDUpOiIsIG51bV9zaWduaWZpY2FudCwgIlxuIikKICBjYXQoIk51bWJlciBvZiB1cHJlZ3VsYXRlZCBnZW5lcyAoYXZnX2xvZzJGQyA+IDEpOiIsIG51bV91cHJlZ3VsYXRlZCwgIlxuIikKICBjYXQoIk51bWJlciBvZiBkb3ducmVndWxhdGVkIGdlbmVzIChhdmdfbG9nMkZDIDwgLTEpOiIsIG51bV9kb3ducmVndWxhdGVkLCAiXG4iKQp9CgpgYGAKCiMjIDYuMiBTdW1tYXJpemUgTWFya2VyczEgKE1BU1Qgd2l0aCBTQ1QgQXNzYXkpCmBgYHtyfQpjYXQoIk1hcmtlcnMxIFN1bW1hcnkgKE1BU1Qgd2l0aCBTQ1QgQXNzYXkpOlxuIikKc3VtbWFyaXplX21hcmtlcnMobWFya2Vyc19tYXN0X1NDVCkKCmBgYAoKIyMgNi4zIFN1bW1hcnkgZm9yIE1hcmtlcnMyIChNQVNUIHdpdGggUk5BIEFzc2F5KQpgYGB7cn0KY2F0KCJNYXJrZXJzMiBTdW1tYXJ5IChNQVNUIHdpdGggUk5BIEFzc2F5KTpcbiIpCnN1bW1hcml6ZV9tYXJrZXJzKG1hcmtlcnNfbWFzdF9STkEpCmBgYAoKIyMgQ29tcGFyZSBSZXN1bHRzIEJldHdlZW4gU0NUIGFuZCBSTkEgQXNzYXlzCmBgYHtyfQojIyMgQ29tcGFyZSBSZXN1bHRzIEJldHdlZW4gUk5BIGFuZCBTQ1QgQXNzYXlzCgojIExvYWQgZ2VuZSBzZXRzCmdlbmVzX21hc3Rfc2N0IDwtIG1hcmtlcnNfbWFzdF9TQ1QkZ2VuZQpnZW5lc19tYXN0X3JuYSA8LSBtYXJrZXJzX21hc3RfUk5BJGdlbmUKY29tbW9uX2dlbmVzX21hc3QgPC0gaW50ZXJzZWN0KGdlbmVzX21hc3Rfc2N0LCBnZW5lc19tYXN0X3JuYSkKCmNhdCgiTUFTVDogQ29tbW9uIEdlbmVzIEJldHdlZW4gU0NUIGFuZCBSTkE6IiwgbGVuZ3RoKGNvbW1vbl9nZW5lc19tYXN0KSwgIlxuIikKCmBgYAoKCiMgNy4gVmlzdWFsaXphdGlvbgoKIyMgNy4xIFZvbGNhbm8gUGxvdCBmb3IgTUFTVC1TQ1Qgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgpFbmhhbmNlZFZvbGNhbm8obWFya2Vyc19tYXN0X1NDVCwKICAgICAgICAgICAgICAgIGxhYiA9IG1hcmtlcnNfbWFzdF9TQ1QkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNYWxpZ25hbnRfdnNfTm9ybWFsX01BU1RfU0NUIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjApCgpgYGAKCiMjIDcuMiBWb2xjYW5vIFBsb3QgTUFTVC1STkEgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgpFbmhhbmNlZFZvbGNhbm8obWFya2Vyc19tYXN0X1JOQSwKICAgICAgICAgICAgICAgIGxhYiA9IG1hcmtlcnNfbWFzdF9STkEkZ2VuZSwKICAgICAgICAgICAgICAgIHggPSAiYXZnX2xvZzJGQyIsCiAgICAgICAgICAgICAgICB5ID0gInBfdmFsX2FkaiIsCiAgICAgICAgICAgICAgICB0aXRsZSA9ICJNYWxpZ25hbnRfdnNfTm9ybWFsX01BU1RfUk5BIiwKICAgICAgICAgICAgICAgIHBDdXRvZmYgPSAwLjA1LAogICAgICAgICAgICAgICAgRkNjdXRvZmYgPSAxLjApCgpgYGAKCiMjIDcuMyBWb2xjYW5vIFBsb3QgTUFTVC1STkEgd2l0aCBCYXRjaCBDb3JyZWN0aW9uCmBgYHtyLCBmaWcuaGVpZ2h0PTEyLCBmaWcud2lkdGg9MTJ9CgojIyMgMS4gTG9hZCBEYXRhIGFuZCBQcmVwYXJlIGZvciBDb21wYXJpc29uCgpsaWJyYXJ5KGdncGxvdDIpCgpkZl9zY3QgPC0gcmVhZC5jc3YoIi4uLzAtcm9iai8xLU1BU1Rfd2l0aF9TQ1RfYmF0Y2hfcGF0aWVudF9jZWxsbGluZV9hc19Db3ZhcmlhdGUuY3N2Iiwgcm93Lm5hbWVzID0gMSkKZGZfcm5hIDwtIHJlYWQuY3N2KCIuLi8wLXJvYmovMi1NQVNUX3dpdGhfUk5BX2JhdGNoX3BhdGllbnRfY2VsbGxpbmVfYXNfQ292YXJpYXRlLmNzdiIsIHJvdy5uYW1lcyA9IDEpCgpkZl9zY3QkYXNzYXkgPC0gIlNDVCIKZGZfcm5hJGFzc2F5IDwtICJSTkEiCgpkZl9jb21iaW5lZCA8LSByYmluZChkZl9zY3QsIGRmX3JuYSkKCiMjIyAyLiBWb2xjYW5vIFBsb3QgZm9yIFNDVCB2cyBSTkEgQ29tcGFyaXNvbgoKZ2dwbG90KGRmX2NvbWJpbmVkLCBhZXMoeCA9IGF2Z19sb2cyRkMsIHkgPSAtbG9nMTAocF92YWxfYWRqKSwgY29sb3IgPSBhc3NheSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC43KSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIlZvbGNhbm8gUGxvdDogUk5BIHZzIFNDVCIsIHggPSAiTG9nMiBGb2xkIENoYW5nZSIsIHkgPSAiLUxvZzEwIEFkanVzdGVkIFAtdmFsdWUiKSArCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGMoIlNDVCIgPSAiYmx1ZSIsICJSTkEiID0gInJlZCIpKQoKYGBgCgoKIyMgNy40IENvcnJlbGF0aW9uIG9mIExvZzIgRm9sZCBDaGFuZ2UgQmV0d2VlbiBSTkEgYW5kIFNDVApgYGB7ciwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyfQoKIyBDb3JyZWxhdGlvbiBvZiBMb2cyIEZvbGQgQ2hhbmdlIEJldHdlZW4gUk5BIGFuZCBTQ1QKIyBHb2FsOiBTZWUgaWYgZ2VuZXMgaGF2ZSBjb25zaXN0ZW50IGZvbGQgY2hhbmdlcyBiZXR3ZWVuIFJOQSBhbmQgU0NUIG5vcm1hbGl6YXRpb24uCgoKbGlicmFyeShkcGx5cikgICMgTG9hZCBkcGx5ciB0byB1c2Ugcm93bmFtZXNfdG9fY29sdW1uCgoKIyBDb252ZXJ0IHJvdyBuYW1lcyB0byBhICJnZW5lIiBjb2x1bW4KZGZfc2N0IDwtIGRmX3NjdCAlPiUgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJnZW5lIikKZGZfcm5hIDwtIGRmX3JuYSAlPiUgcm93bmFtZXNfdG9fY29sdW1uKHZhciA9ICJnZW5lIikKCiMgTWVyZ2UgZGF0YXNldHMgYnkgZ2VuZQpkZl9tZXJnZWQgPC0gbWVyZ2UoZGZfc2N0LCBkZl9ybmEsIGJ5ID0gImdlbmUiLCBzdWZmaXhlcyA9IGMoIl9TQ1QiLCAiX1JOQSIpKQoKIyBTY2F0dGVyIHBsb3Qgb2YgbG9nMkZDIHZhbHVlcwpnZ3Bsb3QoZGZfbWVyZ2VkLCBhZXMoeCA9IGF2Z19sb2cyRkNfU0NULCB5ID0gYXZnX2xvZzJGQ19STkEpKSArCiAgZ2VvbV9wb2ludChhbHBoYSA9IDAuNywgY29sb3IgPSAiYmx1ZSIpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iLCBjb2xvciA9ICJyZWQiLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICBsYWJzKHRpdGxlID0gIkxvZzIgRm9sZCBDaGFuZ2UgQ29tcGFyaXNvbjogU0NUIHZzIFJOQSIsCiAgICAgICB4ID0gIlNDVCBMb2cyIEZvbGQgQ2hhbmdlIiwKICAgICAgIHkgPSAiUk5BIExvZzIgRm9sZCBDaGFuZ2UiKSArCiAgZ2VvbV9hYmxpbmUoc2xvcGUgPSAxLCBpbnRlcmNlcHQgPSAwLCBsaW5ldHlwZSA9ICJkb3R0ZWQiLCBjb2xvciA9ICJibGFjayIpCmBgYAoKCiMjIDcuNSBGaW5kIG92ZXJsYXAgYmV0d2VlbiB0aGUgdG9wIDEwMCBtb3N0IHNpZ25pZmljYW50IGdlbmVzOgpgYGB7ciwgZmlnLmhlaWdodD0xMiwgZmlnLndpZHRoPTEyfQoKY29yKGRmX21lcmdlZCRhdmdfbG9nMkZDX1NDVCwgZGZfbWVyZ2VkJGF2Z19sb2cyRkNfUk5BLCB1c2UgPSAiY29tcGxldGUub2JzIikKCiMgSGlnaGVyIGNvcnJlbGF0aW9uICh+MC44LTEuMCkgc3VnZ2VzdHMgY29uc2lzdGVuY3kgYmV0d2VlbiBtZXRob2RzLgojIExvd2VyIGNvcnJlbGF0aW9uICg8MC42KSBtYXkgaW5kaWNhdGUgZGlmZmVyZW50IG5vcm1hbGl6YXRpb24gZWZmZWN0cy4KCgpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoZHBseXIpCgojIERlZmluZSBhIGJyb2FkZXIgbGlzdCBvZiBrbm93biBTZXphcnkgZ2VuZXMKc2V6YXJ5X2dlbmVzIDwtIGMoIktJUjNETDIiLCAiVE9YIiwgIlRXSVNUMSIsICJDRDUyIiwgIkNDUjQiLCAiSUwyUkEiLCAiQ0Q3IiwgIkRQUDQiLCAiQ0NSNyIsICJHQVRBMyIsICJGT1hQMyIsICJDRDhBIiwgIkNENCIsICJDWVAyN0IxIiwgIlRFVDIiKQoKIyBGaWx0ZXIgdGhlIG1lcmdlZCBkYXRhIHRvIGluY2x1ZGUgb25seSB0aGUga25vd24gU2V6YXJ5IGdlbmVzCmRmX2ZpbHRlcmVkIDwtIGRmX21lcmdlZCAlPiUKICBmaWx0ZXIoZ2VuZSAlaW4lIHNlemFyeV9nZW5lcykKCiMgVm9sY2FubyBwbG90IHNob3dpbmcgb25seSB0aGUga25vd24gU2V6YXJ5IGdlbmVzIHdpdGggZ2VuZSBuYW1lcwpnZ3Bsb3QoZGZfZmlsdGVyZWQsIGFlcyh4ID0gYXZnX2xvZzJGQ19TQ1QsIHkgPSAtbG9nMTAocF92YWxfYWRqX1NDVCksIGNvbG9yID0gZ2VuZSkpICsKICBnZW9tX3BvaW50KGFscGhhID0gMC43KSArCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IGdlbmUpLCB2anVzdCA9IDEuNSwgaGp1c3QgPSAwLjUsIHNpemUgPSAzLCBjb2xvciA9ICJibGFjayIpICsgICMgQWRkaW5nIGdlbmUgbmFtZXMKICB0aGVtZV9taW5pbWFsKCkgKwogIGxhYnModGl0bGUgPSAiVm9sY2FubyBQbG90OiBLbm93biBTZXphcnkgR2VuZXMgKFNDVCBBc3NheSkiLCAKICAgICAgIHggPSAiTG9nMiBGb2xkIENoYW5nZSAoU0NUKSIsIAogICAgICAgeSA9ICItTG9nMTAgQWRqdXN0ZWQgUC12YWx1ZSIpICsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiS0lSM0RMMiIgPSAiIzFmNzdiNCIsICAjIGJsdWUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiVE9YIiA9ICIjZmY3ZjBlIiwgICMgb3JhbmdlCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlRXSVNUMSIgPSAiIzJjYTAyYyIsICAjIGdyZWVuCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENTIiID0gIiM5NDY3YmQiLCAgIyBwdXJwbGUKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0NSNCIgPSAiIzhjNTY0YiIsICAjIGJyb3duCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIklMMlJBIiA9ICIjZTM3N2MyIiwgICMgcGluawogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDciID0gIiM3ZjdmN2YiLCAgIyBncmF5CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkRQUDQiID0gIiNiY2JkMjIiLCAgIyB5ZWxsb3ctZ3JlZW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ0NSNyIgPSAiIzE3YmVjZiIsICAjIGN5YW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR0FUQTMiID0gIiNkNjI3MjgiLCAgIyByZWQKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRk9YUDMiID0gIiM4YTJiZTIiLCAgIyBibHVlLXZpb2xldAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJDRDhBIiA9ICIjZmY2MzQ3IiwgICMgdG9tYXRvCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkNENCIgPSAiIzNjYjM3MSIsICAjIG1lZGl1bSBzZWEgZ3JlZW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ1lQMjdCMSIgPSAiI2ZmMTQ5MyIsICAjIGRlZXAgcGluawogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJURVQyIiA9ICIjMDBiZmZmIikpICsgICMgZGVlcCBza3kgYmx1ZQogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJ0b3AiKQoKYGBg